Python学习-八周四次课(12月14日)

八周四次课(12月14日)
15.3 多线程共享变量
15.4 线程池

 

python多线程可以使任务得到并发执行,但是有时候在执行多次任务的时候,变量出现“意外”。

 

[python] view plain copy
 
  1. import threading,time  
  2. n=0  
  3. start=time.time()  
  4. def b1(num):  
  5.     global n  
  6.     n=n+num  
  7.     n=n-num  
  8. def b2(num):  
  9.     for i in range(1000000):  
  10.         b1(num)  
  11. t1=threading.Thread(target=b2,args=(5,))  
  12. t2=threading.Thread(target=b2,args=(8,))  
  13. t1.start()  
  14. t2.start()  
  15. t1.join()  
  16. t2.join()  
  17. end=time.time()  
  18. print(n)  
  19. print(end-start)  

执行结果:

 

 

[python] view plain copy
 
  1. 18  
  2. 0.7520430088043213  

可见变量n从0变成了18,用时是0.75s,原因是计算机系统计算类似n=n+num是分两步计算的,先计算n+num的值放进内存中,然后再把计算的值赋值给n,正是这个间隙导致了变量出现“意外”。

 

这时候可以使用threading.Lock来把线程中的变量锁定,使用完再释放!

 

[python] view plain copy
 
  1. import threading,time  
  2. n=0  
  3. lock=threading.Lock()  
  4. start=time.time()  
  5. def b1(num):  
  6.     global n  
  7.     n=n+num  
  8.     n=n-num  
  9. def b2(num):  
  10.     for i in range(1000000):  
  11.             lock.acquire()#等待获取或获取修改变量的权限,并霸占它们  
  12.             b1(num)  
  13.             lock.release()#释放霸占的变量  
  14. t1=threading.Thread(target=b2,args=(5,))  
  15. t2=threading.Thread(target=b2,args=(8,))  
  16. t1.start()  
  17. t2.start()  
  18. t1.join()  
  19. t2.join()  
  20. end=time.time()  
  21. print(n)  
  22. print(end-start)  

执行结果:

 

 

[python] view plain copy
 
  1. 0  
  2. 3.335190773010254  

虽然变量的值正确了,但慢了很多倍,效率大大的打折扣,多线程的优势也没凸显出来。

所以尽量使用局部变量来代替全局变量在线程中使用,这样可以避免效率的问题。

线程池:

1、安装

使用安装: pip installthreadpool

 

2、使用

    (1)引入threadpool模块
    (2)定义线程函数
    (3)创建线程 池threadpool.ThreadPool()
    (4)创建需要线程池处理的任务即threadpool.makeRequests()
    (5)将创建的多个任务put到线程池中,threadpool.putRequest
    (6)等到所有任务处理完毕theadpool.pool()
[python] view plain copy
 
  1. import threadpool  
  2. def ThreadFun(arg1,arg2):  
  3.     pass  
  4. def main():  
  5.     device_list=[object1,object2,object3......,objectn]#需要处理的设备个数  
  6.     task_pool=threadpool.ThreadPool(8)#8是线程池中线程的个数  
  7.     request_list=[]#存放任务列表  
  8.     #首先构造任务列表  
  9.     for device in device_list:  
  10.         request_list.append(threadpool.makeRequests(ThreadFun,[((device, ), {})]))  
  11.     #将每个任务放到线程池中,等待线程池中线程各自读取任务,然后进行处理,使用了map函数,不了解的可以去了解一下。  
  12.     map(task_pool.putRequest,request_list)  
  13.     #等待所有任务处理完成,则返回,如果没有处理完,则一直阻塞  
  14.     task_pool.poll()  
  15. if __name__=="__main__":  
  16.     main()  
 
上面就是一个具体的线程池的使用流程
threadpool具体的定义如下:
[python] view plain copy
 
  1. class ThreadPool:  
  2.     """A thread pool, distributing work requests and collecting results. 
  3.  
  4.     See the module docstring for more information. 
  5.  
  6.     """  
  7.     def __init__(self, num_workers, q_size=0, resq_size=0, poll_timeout=5):  
  8.         pass  
  9.     def createWorkers(self, num_workers, poll_timeout=5):  
  10.         pass  
  11.     def dismissWorkers(self, num_workers, do_join=False):  
  12.         pass  
  13.     def joinAllDismissedWorkers(self):  
  14.         pass  
  15.     def putRequest(self, request, block=True, timeout=None):  
  16.         pass  
  17.     def poll(self, block=False):  
  18.         pass  
  19.     def wait(self):  
  20.         pass  

 

posted @ 2017-12-14 19:56  zhuntidaoren  阅读(137)  评论(0)    收藏  举报