python 多线程
来源:互联网 发布:图解网络硬件 百度云 编辑:程序博客网 时间:2024/06/06 17:29
进程、线程之间的关系
打个比方:如果有一个车间,车间里面有工人在工作。那么进程就相当于这个车间,而线程就相当于车间里面工作的工人。
是不是差不多明白点了。进程不能运行,它是一些资源的封装体,主要是cpu,io,内存资源,好比车间里的电和工具一样。每个进程要运行至少需要一个线程,这个线程就是主线程。线程是负责干具体的工作的。
单线程的例子:
import timedef eat(food): print ("eat %s" %food) print("start:", time.ctime()) time.sleep(2) print (time.ctime())def play(name): print ("play %s" %name) time.sleep(5) print (time.ctime())if __name__=="__main__": eat("宫保鸡丁") play("篮球") print (time.ctime())结果: eat 宫保鸡丁 start: Wed Nov 29 21:05:26 2017 Wed Nov 29 21:05:28 2017 play 篮球 Wed Nov 29 21:05:33 2017 Wed Nov 29 21:05:33 2017
定义一个吃和玩的例子。可以看到,程序的运行的总时间是等于所以时间之和。
多线程例子:
import timeimport threadingdef eat(food): print ("eat %s" %food) print ("start:",time.ctime()) time.sleep(2) print ("eat",time.ctime())def play(name): print ("play %s" %name) time.sleep(5) print ("play",time.ctime())t1 = threading.Thread(target=eat,args=("宫保鸡丁",))t2 = threading.Thread(target=play,args=("篮球",))if __name__=="__main__": t1.start() t2.start() print ("main:",time.ctime())结果: eat 宫保鸡丁 start: Wed Nov 29 20:58:48 2017 play 篮球 main: Wed Nov 29 20:58:48 2017 eat Wed Nov 29 20:58:50 2017 play Wed Nov 29 20:58:53 2017
可以看出,对比单线程。时间减少了2秒。
多线程的定义:
- 导入threading类
- t1 = threading.Thread(target=eat,args=(“宫保鸡丁”,)) 实例化Thread 类。target= 传入要执行的函数,args= 函数的参数。是一个元组。注意后面的逗号。
- t1.start() 运行这个线程
setDaemon守护线程
def eat(food): print ("eat %s" %food) time.sleep(2) print ("eat",time.ctime())def play(name): print ("play %s" %name) time.sleep(5) print ("play",time.ctime())threads = []t1 = threading.Thread(target=eat,args=("宫保鸡丁",))threads.append(t1)t2 = threading.Thread(target=play,args=("篮球",))threads.append(t2)if __name__=="__main__": t1.setDaemon(True) t1.start() t2.setDaemon(True) t2.start() print ("main:",time.ctime()) 结果: eat 宫保鸡丁 play 篮球 main: Thu Nov 30 09:46:38 2017
setDaemon是守护线程,就是守护着主线程。主线程退出子线程就跟着退出。
注意:setDaemon 在start之前
join等待子线程运行完再运行主线程
def eat(food): print ("eat %s" %food) time.sleep(2) print ("eat",time.ctime())def play(name): print ("play %s" %name) time.sleep(5) print ("play",time.ctime())threads = []t1 = threading.Thread(target=eat,args=("宫保鸡丁",))threads.append(t1)t2 = threading.Thread(target=play,args=("篮球",))threads.append(t2)if __name__=="__main__": for t in threads: t.start() for t in threads: t.join() print ("main:",time.ctime())结果:eat 宫保鸡丁play 篮球eat Thu Nov 30 09:48:21 2017play Thu Nov 30 09:48:24 2017main: Thu Nov 30 09:48:24 2017
可以看到主线程的main 最后执行。这里用循环,让两个子线程同时运行,运行完毕再运行主线程
内存共享 + 线程锁
num = 1threads = []lock = threading.Lock()def add_num(): global num lock.acquire() num +=1 lock.release() time.sleep(1)for i in range(500): t = threading.Thread(target=add_num) t.start() threads.append(t)for t in threads: t.join()print (num)结果: 501
内存共享是线程的一个特点,就是多个线程可以修改同一个内存数据。但是有时候会可能多个线程同时修改一个数据造成数据的不正确(在python2中出现过,不多。python3 没有出现)。为了保险起见可以在修改数据之前加一个锁(threading.Lock())。修改之后再释放锁来保证数据不会同时被多个线程占用。
threading.Event 线程事件(引用博友的代码了,写的挺好)
import threading,timeimport randomdef light(): if not event.isSet(): event.set() #wait就不阻塞 #绿灯状态 count = 0 while True: if count < 10: print('\033[42;1m--green light on---\033[0m') elif count <13: print('\033[43;1m--yellow light on---\033[0m') elif count <20: if event.isSet(): event.clear() print('\033[41;1m--red light on---\033[0m') else: count = 0 event.set() #打开绿灯 time.sleep(1) count +=1def car(n): while 1: time.sleep(random.randrange(10)) if event.isSet(): #绿灯 print("car [%s] is running.." % n) else: print("car [%s] is waiting for the red light.." %n)if __name__ == '__main__': event = threading.Event() Light = threading.Thread(target=light) Light.start() for i in range(3): t = threading.Thread(target=car,args=(i,)) t.start()
event = threading.Event() 实例化一个事件
event.isSet()判断是否为True
even.set() 设置为True
even.clear() 设置为False
我觉得event就是设置了一个全局变量,每个线程根据变量的真假做动作。上面代码改为全局变量模式
import threading,timeimport randomflag = Truedef light(): global flag if not flag: flag = True #wait就不阻塞 #绿灯状态 count = 0 while True: if count < 10: print('\033[42;1m--green light on---\033[0m') elif count <13: print('\033[43;1m--yellow light on---\033[0m') elif count <20: if flag: flag = False print('\033[41;1m--red light on---\033[0m') else: count = 0 flag=True #打开绿灯 time.sleep(1) count +=1def car(n): global flag while 1: time.sleep(random.randrange(10)) if flag: #绿灯 print("car [%s] is running.." % n) else: print("car [%s] is waiting for the red light.." %n)if __name__ == '__main__': #event = threading.Event() Light = threading.Thread(target=light) Light.start() for i in range(3): t = threading.Thread(target=car,args=(i,)) t.start()
多线程加queue实现生产者消费者模型。
模型简介:
生产者生产包子,消费者吃包子。如果生产者生产的慢,消费者吃得快。就会导致消费者的等待,在等待的过程中不能干别的事情。所以引入了queue,它就像一个桌子一样,生产完包子将包子放到桌子上,消费者直接去桌子上取。这样消费者不直接依赖生产者,也就实现了解耦。
上代码:
import queueimport threadingimport timeq = queue.Queue()def producer(name): while True: time.sleep(1) q.put("包子") print ("%s 做了一个包子" %name) print (q.qsize())def comsumer(name): while True: time.sleep(2) if not q.empty(): q.get() print("%s 吃了一个包子" %name)for i in range(2): t = threading.Thread(target=producer,args=("大壮",)) t.start()for i in range(3): t = threading.Thread(target=comsumer,args=("小壮实",)) t.start()
- Python多线程
- Python多线程
- Python多线程
- python多线程
- python 多线程
- python多线程
- python多线程
- python 多线程
- python多线程
- Python多线程
- Python 多线程
- python多线程
- python 多线程
- {python多线程}
- Python 多线程
- Python多线程
- python 多线程
- Python 多线程
- 洛谷P3371 【模板】单源最短路径
- 基于mint-ui的移动应用开发案例一(简介)
- 爬虫简要示例 以简书四灵传奇为例
- Java中的强制类型转换
- ORA-28000:the account is locked 用户scott被锁
- python 多线程
- [Kafka]
- JAVA | 32
- 学习真的很难吗?
- 一文读懂Hinton最新Capsules论文
- 将字符串插入另一个字符串的指定位置
- 基于Socket编程,模拟TCP部分协议字段编程
- linux下GNU、G++编辑器的安装及基本使用
- 练习2