多线程、多进程、协程
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #使用线程锁 2 #要在产生资源抢占的地方加锁 3 #一定不要在IO的地方加,否则就变成同步执行了 4 #coding:utf8 5 import threading 6 import time 7 8 lock = threading.Lock() 9 10 def print_time(thread_name,delay): 11 count = 0 12 while count<5: 13 time.sleep(delay) 14 lock.acquire() 15 count+=1 16 print(thread_name,time.ctime(time.time())) 17 lock.release() 18 19 t_name_list = ['t1','t2','t3'] 20 t_list = [] 21 for t_name in t_name_list: 22 work = threading.Thread(target=print_time,args=(t_name,1,)) 23 work.start() 24 t_list.append(work) 25 26 for t in t_list: 27 t.join() 28 29 print 'end---------' 30 31 结果:有序,用锁保证当前线程操作的原子性,共用5s 32 ('t2', 'Mon May 21 11:52:36 2018') 33 ('t1', 'Mon May 21 11:52:36 2018') 34 ('t3', 'Mon May 21 11:52:36 2018') 35 ('t1', 'Mon May 21 11:52:37 2018') 36 ('t2', 'Mon May 21 11:52:37 2018') 37 ('t3', 'Mon May 21 11:52:37 2018') 38 ('t1', 'Mon May 21 11:52:38 2018') 39 ('t2', 'Mon May 21 11:52:38 2018') 40 ('t3', 'Mon May 21 11:52:38 2018') 41 ('t3', 'Mon May 21 11:52:39 2018') 42 ('t1', 'Mon May 21 11:52:39 2018') 43 ('t2', 'Mon May 21 11:52:39 2018') 44 ('t2', 'Mon May 21 11:52:40 2018') 45 ('t1', 'Mon May 21 11:52:40 2018') 46 ('t3', 'Mon May 21 11:52:40 2018') 47 end---------
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 线程池的方式 2 3 #coding:utf8 4 import threading 5 import time 6 import threadpool 7 8 lock = threading.Lock() 9 10 def print_time(thread_name): 11 count = 0 12 while count<5: 13 time.sleep(1) 14 lock.acquire() 15 count+=1 16 print(thread_name,time.ctime(time.time())) 17 lock.release() 18 19 t_name_list = ['t1','t2','t3'] 20 pool = threadpool.ThreadPool(2) 21 requests = threadpool.makeRequests(print_time, t_name_list) 22 for req in requests: 23 pool.putRequest(req) 24 pool.wait() 25 print 'end---------' 26 27 28 结果:有序,10s 29 ('t1', 'Mon May 21 15:02:22 2018') 30 ('t2', 'Mon May 21 15:02:22 2018') 31 ('t1', 'Mon May 21 15:02:23 2018') 32 ('t2', 'Mon May 21 15:02:23 2018') 33 ('t1', 'Mon May 21 15:02:24 2018') 34 ('t2', 'Mon May 21 15:02:24 2018') 35 ('t1', 'Mon May 21 15:02:25 2018') 36 ('t2', 'Mon May 21 15:02:25 2018') 37 ('t1', 'Mon May 21 15:02:26 2018') 38 ('t2', 'Mon May 21 15:02:26 2018') 39 ('t3', 'Mon May 21 15:02:27 2018') 40 ('t3', 'Mon May 21 15:02:28 2018') 41 ('t3', 'Mon May 21 15:02:29 2018') 42 ('t3', 'Mon May 21 15:02:30 2018') 43 ('t3', 'Mon May 21 15:02:32 2018') 44 end---------
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 自己实现的线程池,有很多问题,但大致原理是对的 2 #coding:utf8 3 import threading 4 import Queue 5 import time 6 7 lock = threading.Lock() 8 9 class ThreadPool(): 10 def __init__(self,max_num=20): 11 self._max_num = max_num 12 self.queue = Queue.Queue(max_num) 13 for i in range(max_num): 14 self.queue.put(threading.Thread) 15 16 def get_thread(self): 17 return self.queue.get() 18 19 def add_thread(self): 20 self.queue.put(threading.Thread) 21 22 def func(pool,a1): 23 time.sleep(1) 24 lock.acquire() 25 print(a1) 26 lock.release() 27 pool.add_thread() 28 29 p = ThreadPool() 30 for i in range(100): 31 thread = p.get_thread() 32 t = thread(target=func, args=(p, i,)) 33 t.start()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #使用系统自带的库 2 from concurrent.futures import ThreadPoolExecutor,wait 3 import time 4 5 #创建线程池 6 pool = ThreadPoolExecutor(max_workers=2) 7 8 #线程池中实现了线程安全,不用加锁了 9 def print_time(thread_name): 10 count = 0 11 while count<5: 12 time.sleep(1) 13 count+=1 14 print(thread_name,time.ctime(time.time())) 15 16 17 t_name_list = ['t1','t2','t3'] 18 19 fs = [] 20 for t_name in t_name_list: 21 f = pool.submit(print_time,t_name) 22 fs.append(f) 23 #相遇与join,阻塞主线程 24 wait(fs) 25 print('end---------') 26 27 结果:有序,10s 28 t2 Mon May 21 21:26:38 2018 29 t1 Mon May 21 21:26:38 2018 30 t1 Mon May 21 21:26:39 2018 31 t2 Mon May 21 21:26:39 2018 32 t2 Mon May 21 21:26:40 2018 33 t1 Mon May 21 21:26:40 2018 34 t2 Mon May 21 21:26:41 2018 35 t1 Mon May 21 21:26:41 2018 36 t2 Mon May 21 21:26:42 2018 37 t1 Mon May 21 21:26:42 2018 38 t3 Mon May 21 21:26:43 2018 39 t3 Mon May 21 21:26:44 2018 40 t3 Mon May 21 21:26:45 2018 41 t3 Mon May 21 21:26:46 2018 42 t3 Mon May 21 21:26:47 2018 43 end---------
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #使用gevent,即协程,使用方法和线程类似 2 from gevent import monkey 3 #monkey补丁,改变底层 4 monkey.patch_all() 5 import gevent 6 import time 7 8 #协程的方式 9 10 def print_time(thread_name): 11 count = 0 12 while count<5: 13 gevent.sleep(1) 14 count+=1 15 print(thread_name,time.ctime(time.time())) 16 17 18 t_name_list = ['t1','t2','t3'] 19 gs = [] 20 for t_name in t_name_list: 21 g = gevent.spawn(print_time,t_name) 22 gs.append(g) 23 for g1 in gs: 24 g1.join() 25 print('end-----') 26 27 结果:有序,5s 28 t1 Mon May 21 21:50:23 2018 29 t2 Mon May 21 21:50:23 2018 30 t3 Mon May 21 21:50:23 2018 31 t1 Mon May 21 21:50:24 2018 32 t2 Mon May 21 21:50:24 2018 33 t3 Mon May 21 21:50:24 2018 34 t1 Mon May 21 21:50:25 2018 35 t2 Mon May 21 21:50:25 2018 36 t3 Mon May 21 21:50:25 2018 37 t1 Mon May 21 21:50:26 2018 38 t2 Mon May 21 21:50:26 2018 39 t3 Mon May 21 21:50:26 2018 40 t1 Mon May 21 21:50:27 2018 41 t2 Mon May 21 21:50:27 2018 42 t3 Mon May 21 21:50:27 2018 43 end-----
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #协程池的方式,感觉意义不大 2 from gevent import monkey 3 monkey.patch_all() 4 import gevent 5 import time 6 from gevent.pool import Pool 7 8 #协程池的方式 9 pool = Pool(2) 10 11 def print_time(thread_name): 12 count = 0 13 while count<5: 14 gevent.sleep(1) 15 count+=1 16 print(thread_name,time.ctime(time.time())) 17 18 19 t_name_list = ['t1','t2','t3'] 20 gs = [] 21 for t_name in t_name_list: 22 pool.spawn(print_time,t_name) 23 pool.join() 24 print('end-----') 25 26 结果:有序,10s 27 t1 Mon May 21 21:48:30 2018 28 t2 Mon May 21 21:48:30 2018 29 t1 Mon May 21 21:48:31 2018 30 t2 Mon May 21 21:48:31 2018 31 t1 Mon May 21 21:48:32 2018 32 t2 Mon May 21 21:48:32 2018 33 t1 Mon May 21 21:48:33 2018 34 t2 Mon May 21 21:48:33 2018 35 t1 Mon May 21 21:48:34 2018 36 t2 Mon May 21 21:48:34 2018 37 t3 Mon May 21 21:48:35 2018 38 t3 Mon May 21 21:48:36 2018 39 t3 Mon May 21 21:48:37 2018 40 t3 Mon May 21 21:48:38 2018 41 t3 Mon May 21 21:48:39 2018 42 end-----
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #coding:utf8 2 import threading 3 import time 4 5 class make_baozi(threading.Thread): 6 def __init__(self, id, sem): 7 super(make_baozi,self).__init__() 8 self.url = id 9 self.sem = sem 10 11 def run(self): 12 time.sleep(2) 13 print("make a baozi") 14 self.sem.release() # 内部维护的计数器加1,并通知内部维护的conditon通知acquire 15 16 class eat_baozi(threading.Thread): 17 def __init__(self, sem): 18 super(eat_baozi,self).__init__() 19 self.sem = sem 20 21 def run(self): 22 for i in range(20): 23 self.sem.acquire() # 内部维护的计数器减1,到0就会阻塞 24 make_thread = make_baozi(i,sem) 25 make_thread.start() 26 print('eat maozi %s'%i) 27 28 if __name__ == '__main__': 29 sem = threading.Semaphore(3) #设置同时最多3个 30 url_producer = eat_baozi(sem) 31 url_producer.start() 32 33 34 35 #结果3个一出 36 eat maozi 3 37 eat maozi 4 38 eat maozi 5 39 make a baozi 40 make a baozi 41 make a baozi
技术对比:
总结:I/O密集的场景下尽量使用协程来完成任务