zoukankan      html  css  js  c++  java
  • 多线程、多进程、协程

    多线程
     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---------
    加了锁的多线程
     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---------
    threadpool库实现
     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()
    自己实现线程池
     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---------
    ThreadPoolExecutor线程池
     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-----
    协程(gevent)
     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-----
    协程池(gevent.pool)
     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密集的场景下尽量使用协程来完成任务

  • 相关阅读:
    聊一聊Java泛型的擦除
    微信退款通知信息解密
    Spring Boot 初识
    shiro初识
    Redis 初探
    Java Json库的选取准则
    JAVA 几款Json library的比较
    FUSE简介
    Lab 2 源码分析
    Lab2
  • 原文地址:https://www.cnblogs.com/cx59244405/p/9069667.html
Copyright © 2011-2022 走看看