多进程与多线程
线程和进程:
进程:对于操作系统来说,打开一个记事本是进程,打开一个word是一个word进行,打开QQ也是一个进程。进程是很多资源的集合。
线程:打开word后,word可以同时进行打字,拼写检查,打印等事情。在一个进程内部,要同时干很多事,就需要同时运行多个‘子任务’,就把进程内的这些‘子任务’称为线程
每个进程值是要干一件事,所有一个进程至少有一个线程。多线程可以同时执行,多线程的执行方式和多进程一样,也是由操作系统在多个线程之间快速切换,让每个线程都短暂的交替进行,看起来像同时执行一样。当然,真正的同时执行多线程需要多核cpu才可能实现。线程是最小的执行单元,而进程由至少一个线程组成。
python的解释器使用了GIL的一个叫全局解释器锁,它不能利用多核cpu,只能运行在一个CPU上面,但是在运行程序的时候,看起来好像还是在一起运动,是因为操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换到任务2,任务2执行0.01秒,再切换到任务3,执行0.01秒。。。这样反复执行下去。表面上看,每个任务都是交替执行的,但是由于cpu的执行速度太快了,感觉就像所有任务都在同时执行一样,这个称为上下文切换。
1 ''' 2 多线程: 3 咱们打开的程序都是一个进程。 4 线程是包含在进程里的。 5 进程里面最少有一个线程 6 线程之间是互相独立的 7 有一个主线程 8 ''' 9 ''' 10 cpu是几核的,就只能同时运行几个进程 11 12 python的多线程是利用不了多核cpu的,GIL全局解释器锁的 13 ''' 14 import threading,time,requests 15 def sayHi(name): 16 time.sleep(2) 17 print(name) 18 sayHi('lkj') 19 sayHi('edc') 20 sayHi('rfv')#串行运行,需要6秒 21 22 23 import threading,time,requests 24 def sayHi(name): 25 time.sleep(2) 26 print(name) 27 t=threading.Thread(target=sayHi,args=('xiahei',))#启动线程 28 t.start()#开始运行 29 30 31 import threading,time,requests 32 def sayHi(name): 33 time.sleep(2) 34 print(name) 35 for i in range(5):#并行运行,需要两秒 36 t=threading.Thread(target=sayHi,args=('xiahei',))#启动线程 37 t.start()#开始运行
1 import threading,time,requests 2 def DownHtml(url,name): 3 comment=requests.get(url).content 4 f=open(name+'.html','wb') 5 f.write(comment) 6 f.close() 7 urls=[ 8 ['nnzhp','http://www.nnzhp.cn'], 9 ['dsx','http://www.imdsx.cn'], 10 ['besttest','http://www.besttest.cn'], 11 ] 12 start_time=time.time() 13 for url in urls: 14 DownHtml(url[1],url[0]) 15 end_time=time.time() 16 print(end_time-start_time)#串行运行,时间较长,4.8s 17 18 19 import threading,time,requests 20 def DownHtml(url,name): 21 comment=requests.get(url).content 22 f=open(name+'.html','wb') 23 f.write(comment) 24 f.close() 25 urls=[ 26 ['nnzhp','http://www.nnzhp.cn'], 27 ['dsx','http://www.imdsx.cn'], 28 ['besttest','http://www.besttest.cn'], 29 ] 30 start_time=time.time() 31 for url in urls: 32 t=threading.Thread(target=DownHtml,args=(url[1],url[0])) 33 t.start() 34 end_time=time.time() 35 print(end_time-start_time)#时间为0.002秒,时间太短,这个时间不对。因为每个进程至少有一个线程,称为主线程;主线程会自己执行自己的,不会等子线程,所以执行到最后一条语句时,就输出时间,所以该时间是主线程的执行时间。
1 import threading,time 2 import requests 3 def DownHtml(url,name): 4 comment=requests.get(url).content 5 f=open(name+'.html','wb') 6 f.write(comment) 7 f.close() 8 urls=[ 9 ['nnzhp','http://www.nnzhp.cn'], 10 ['dsx','http://www.imdsx.cn'], 11 ['besttest','http://www.besttest.cn'], 12 ] 13 start_time=time.time() 14 threads=[]#存放刚才启动线程 15 for url in urls: 16 t=threading.Thread(target=DownHtml,args=(url[1],url[0])) 17 t.start() 18 threads.append(t) 19 for t in threads:#等待子线程 20 t.join()#主线程等待子线程 21 end_time=time.time() 22 print(end_time-start_time)
1 多进程
import multiprocessing,threading 2 import time 3 def run2(): 4 print('这是多线程启动的') 5 def run(): 6 time.sleep(2) 7 for i in range(5): 8 t = threading.Thread(target=run2) 9 t.start() 10 if __name__ == '__main__': 11 for i in range(5): 12 p = multiprocessing.Process(target=run)#Python里面的多线程,是不能利用多核CPU的,如果想利用多核CPU的话,就得使用多进程,python中多进程使用multiprocessing模块。 13 p.start()
守护进程:
1 import threading 2 import time 3 def sh(): 4 time.sleep(2) 5 print("测试守护线程") 6 for i in range(5): 7 t=threading.Thread(target=sh) 8 t.start() 9 print('done') 10 打印结果: 11 done 12 测试守护线程 13 测试守护线程 14 测试守护线程 15 测试守护线程 16 测试守护线程 17 18 19 20 import threading 21 import time 22 def sh(): 23 time.sleep(2) 24 print("测试守护线程") 25 for i in range(5): 26 t=threading.Thread(target=sh) 27 t.setDaemon(True)#设置子线程为守护线程,守护线程就是,一旦主线程执行结束,那么子线程立刻结束,不管子线程有没有运行完 28 t.start() 29 print('done') 30 打印结果: 31 done 32 33 34 import threading 35 import time 36 def sh(): 37 time.sleep(2) 38 print('测试线程') 39 threads=[] 40 for i in range(5): 41 t=threading.Thread(target=sh) 42 t.setDaemon(True)#如果主线程等待子线程的话,那么设置的守护线程就不好使了 43 t.start() 44 threads.append(t) 45 for t in threads: 46 t.join() 47 print('done') 48 打印结果: 49 测试线程 50 测试线程 51 测试线程 52 测试线程 53 测试线程 54 done
线程锁:
1 import threading 2 from threading import Lock 3 4 num = 0 5 lock = Lock() # 申请一把锁 6 7 def run(): 8 global num 9 lock.acquire() # 加锁 10 num += 1 11 lock.release() # 解锁 12 13 lis = [] 14 for i in range(5): 15 t = threading.Thread(target=run) 16 t.start() 17 lis.append(t) 18 for t in lis: 19 t.join() 20 print('over', num) 21 22 23 #加锁是为了多线程的时候同时还修改一个数据的时候,有可能会导致数据不正确 24 #python3里面锁不加也无所谓,它会自动给你加上锁