1、单线程

import time
import urllib2def get_responses():urls = ['http://www.google.com','http://www.amazon.com','http://www.ebay.com','http://www.alibaba.com','http://www.reddit.com']start = time.time()for url in urls:print urlresp = urllib2.urlopen(url)print resp.getcode()print "Elapsed time: %s" % (time.time()-start)get_responses()

解释:

url顺序的被请求 
除非cpu从一个url获得了回应,否则不会去请求下一个url 
网络请求会花费较长的时间,所以cpu在等待网络请求的返回时间内一直处于闲置状态。

2、多线程

import urllib2
import time
from threading import Threadclass GetUrlThread(Thread):def __init__(self, url):self.url = url super(GetUrlThread, self).__init__()def run(self):resp = urllib2.urlopen(self.url)print self.url, resp.getcode()def get_responses():urls = ['http://www.google.com', 'http://www.amazon.com', 'http://www.ebay.com', 'http://www.alibaba.com', 'http://www.reddit.com']start = time.time()threads = []for url in urls:t = GetUrlThread(url)threads.append(t)t.start()for t in threads:t.join()print "Elapsed time: %s" % (time.time()-start)get_responses()

解释: 
意识到了程序在执行时间上的提升 
我们写了一个多线程程序来减少cpu的等待时间,当我们在等待一个线程内的网络请求返回时,这时cpu可以切换到其他线程去进行其他线程内的网络请求。 
我们期望一个线程处理一个url,所以实例化线程类的时候我们传了一个url。 
线程运行意味着执行类里的run()方法。 
无论如何我们想每个线程必须执行run()。 
为每个url创建一个线程并且调用start()方法,这告诉了cpu可以执行线程中的run()方法了。 
我们希望所有的线程执行完毕的时候再计算花费的时间,所以调用了join()方法。 
join()可以通知主线程等待这个线程结束后,才可以执行下一条指令。 
每个线程我们都调用了join()方法,所以我们是在所有线程执行完毕后计算的运行时间。 
关于线程: 
cpu可能不会在调用start()后马上执行run()方法。 
你不能确定run()在不同线程建间的执行顺序。 
对于单独的一个线程,可以保证run()方法里的语句是按照顺序执行的。 
这就是因为线程内的url会首先被请求,然后打印出返回的结果。

解决资源竞争

from threading import Lock, Thread
lock = Lock()
some_var = 0class IncrementThread(Thread):def run(self):#we want to read a global variable#and then increment itglobal some_varlock.acquire()read_value = some_varprint "some_var in %s is %d" % (self.name, read_value)some_var = read_value + 1print "some_var in %s after increment is %d" % (self.name, some_var)lock.release()def use_increment_thread():threads = []for i in range(50):t = IncrementThread()threads.append(t)t.start()for t in threads:t.join()print "After 50 modifications, some_var should have become 50"print "After 50 modifications, some_var is %d" % (some_var,)use_increment_thread()

解释: 
Lock 用来防止竞争条件 
如果在执行一些操作之前,线程t1获得了锁。其他的线程在t1释放Lock之前,不会执行相同的操作 
我们想要确定的是一旦线程t1已经读取了some_var,直到t1完成了修改some_var,其他的线程才可以读取some_var 
这样读取和修改some_var成了逻辑上的原子操作

加锁保证操作的原子性

from threading import Thread, Lock
import timelock = Lock()class CreateListThread(Thread):def run(self):self.entries = []for i in range(10):time.sleep(0.01)self.entries.append(i)lock.acquire()print self.entrieslock.release()def use_create_list_thread():for i in range(3):t = CreateListThread()t.start()use_create_list_thread()

证明了一个线程不可以修改其他线程内部的变量(非全局变量)。

Python多线程简易版:线程池 threadpool

import threadpool
import time
import urllib2urls = ['http://www.google.com', 'http://www.amazon.com', 'http://www.ebay.com', 'http://www.alibaba.com', 'http://www.reddit.com'
]def myRequest(url):resp = urllib2.urlopen(url)print url, resp.getcode()def timeCost(request, n):print "Elapsed time: %s" % (time.time()-start)start = time.time()
pool = threadpool.ThreadPool(5)
reqs = threadpool.makeRequests(myRequest, urls, timeCost)
[ pool.putRequest(req) for req in reqs ]
pool.wait()

makeRequests创建了要开启多线程的函数,以及函数相关参数和回调函数,其中回调函数可以不写,default是无,也就是说makeRequests只需要2个参数就可以运行;

注意:threadpool 是非线程安全的。

转载于:https://www.cnblogs.com/zhaojihui/p/7284721.html

理解 Python 中的多线程相关推荐

  1. 深入理解Python中的全局解释锁GIL

    深入理解Python中的全局解释锁GIL 转自:https://zhuanlan.zhihu.com/p/75780308 注:本文为蜗牛学院资深讲师卿淳俊老师原创,首发自公众号https://mp. ...

  2. PYTHON 中的多线程

    通常我们构建的应用程序可能需要多个任务在同一个应用程序中同时运行.这就是python中多线程概念发挥作用的地方.这篇文章提供了在 Python 中使用多线程(又名 Python 中的线程)的全面解释. ...

  3. python参数传递方法_深入理解python中函数传递参数是值传递还是引用传递

    python 的 深入理解python中函数传递参数是值传递还是引用传递 目前网络上大部分博客的结论都是这样的: Python不允许程序员选择采用传值还是传 引用.Python参数传递采用的肯定是&q ...

  4. python中元组_理解python中的元组

    理解 python 中的元组 引言 在 Python 中元组是这样的: 元组是是这样一种数据结构:不变的或者不可改变的(简单来说不能重新赋值) .元素的有序序列.因为元组是 不变的,所以他的数值是不能 ...

  5. python中继承是什么意思_如何理解Python中的继承?python入门

    如何理解Python中的继承?如今,python编程语言深受企业和个人的喜爱.python开发工程师是近年来互联网行业非常热门的职业岗位之一.学习python的人除了零基础的,还有一部分是在职运维.在 ...

  6. python装饰器作用-理解python中的装饰器

    一 什么是装饰器? 正如其名,装饰器的作用是为已经存在的对象增加额外功能(装饰),由此可使已有函数在无需代码改动的情况下增加额外功能:装饰器的本质是嵌套的函数且返回函数对象,即闭包.有关闭包的概念,可 ...

  7. python怎么导入包-如何理解Python中包的引入

    Python的from import *和from import *,它们的功能都是将包引入使用,但是它们是怎么执行的以及为什么使用这种语法呢? 从一模块导入全部功能 from import * me ...

  8. 如何简单地理解Python中的if __name__ == '__main__'

    如何简单地理解Python中的if __name__ == '__main__' 文章目录: 一.摘要 二. 程序入口 虽然已经知道这个具体的用法,但是这篇文章有很多细节写的还是很好,决定转载一下,日 ...

  9. 全面理解python中self的用法

    self代表类的实例,而非类. class Test:def prt(self):print(self)print(self.__class__)t = Test() t.prt() 执行结果如下 & ...

最新文章

  1. python中的排序方法都有哪些_几种常见的排序方法总结(Python)
  2. 爱奇艺谢丹铭:用AI让创作者提升效率,让消费者简单快乐丨MEET2021
  3. PostgreSQL在何处处理 sql查询之三十八
  4. JavaWeb:用JDBC操作数据库
  5. 使用Win32汇编开发一个dll并在C#中调用
  6. BugKuCTF WEB 变量1
  7. Vue 全家桶 + Express 实现的博客(后端API全部自己手写)
  8. 【opencv学习】【运动物体检测】
  9. linux说明是集群,集群——菜鸟学习Linux集群之概念篇
  10. Star-shaped polygon
  11. 【全网最新最全28套】Java毕业设计项目合集_轻松完成毕设_Java实战项目/Java练手项目
  12. 笔记本拆c面_给老笔记本更换高清屏的经验与总结(翻车记录)
  13. 成形滤波器(利用FDATOOL设计成形滤波器)
  14. mysql的填充因子_SQL Server表索引:调整填充因子
  15. read/write函数
  16. DNS基础:域名解析、多重域名解析、特殊域名解析、主从同步设置
  17. 北邮php,周琳娜-北京邮电大学网络空间安全学院
  18. [CF1091F](New Year and the Mallard Expedition)
  19. Drawio使用介绍(画图工具)
  20. 存货账龄分析报表(中四)

热门文章

  1. mysql+sql+子查询语句_SQL子查询
  2. 安卓开发仿微信图片拖拽_使用Android 模仿微信朋友圈图片拖拽返回
  3. html5本地缓存如何提交,HTML5: 本地缓存
  4. 员工工号怎么编码_华为员工感慨:工号就留在这了,感谢公司给我自己写墓志铭的机会...
  5. 正则表达式的含义php,求正则表达式含义
  6. 【知识星球】卷积核和感受野可动态分配的分组卷积
  7. 【杂谈】从GitHub上星星最多的男人开始发GitHub综述资料
  8. 全球及中国有色金属行业未来发展走势与投资机遇研究报告2022版
  9. 全球及中国综艺节目产业营销策略分析及创新格局规划建议报告2021-2027年
  10. VB 长整型和字节数组的转换问题 (LongByte)