zoukankan      html  css  js  c++  java
  • python3 多线程编程

     

    0.什么是线程

    1. 多线程模块

    2. 创建线程的方法

    3. join()方法

    4.isAlive()方法

    5. name属性和daemon属性

    6.线程的同步---锁

    7.线程的同步---Event对象

    8.线程的同步---Condition条件变量


    1. 多线程模块 

    python3对多线程支持的是 threading 模块,应用这个模块可以创建多线程程序,并且在多线程间进行同步和通信。在python3 中,可以通过两种方法来创建线程:

    第一:通过 threading.Thread 直接在线程中运行函数;第二:通过继承 threading.Thread 类来创建线程



    view plain copy

    1. import threading  
    2.   
    3. def threadfun(x,y):         #线程任务函数 threadfun()  
    4.     for i in range(x,y):  
    5.         print(i)  
    6.   
    7. ta = threading.Thread(target=threadfun,args=(1,6))      #创建一个线程ta,执行 threadfun()  
    8. tb = threading.Thread(target=threadfun,args=(10,15))    #创建一个线程tb,执行threadfun()  
    9. ta.start()          #调用start(),运行线程  
    10. tb.start()          #调用start(),运行线程  
    11. '''''打印:1 2 3 4 5 10 11 12 13 14'''  



    2.通过继承 thread.Thread 类 来创建线程 

    这种方法只需要重载 threading.Thread 类的 run 方法,然后调用 start()开启线程就可以了

    [python] view plain copy
    1. import threading  
    2.   
    3. class mythread(threading.Thread):  
    4.     def run(self):  
    5.         for i in range(1,5):  
    6.             print(i)  
    7.   
    8. ma = mythread();  
    9. mb = mythread();  
    10. ma.start()  
    11. mb.start()  



    view plain copy

    1. import threading  
    2. import time  
    3. class mythread(threading.Thread):  
    4.     def run(self):  
    5.         self.i = 1  
    6.         print('%d'%(self.i))  
    7.         self.i = self.i+1  
    8.         time.sleep(1)           #睡眠一秒  
    9.         print('%d'%(self.i))  
    10.         time.sleep(1)  
    11.   
    12. if __name__ == '__main__':  
    13.     ta = mythread()     #实例化线程  
    14.     ta.start()          #开启ta线程  
    15.     ta.join()           #主线程等待 ta线程结束才继续执行  
    16.     print('main thread over')  



    view plain copy

    1. import threading  
    2. import time  
    3. class mythread(threading.Thread):  
    4.     def run(self):  
    5.        time.sleep(2)  
    6.   
    7. if __name__ == '__main__':  
    8.     ta = mythread()     #实例化线程  
    9.     print(ta.isAlive())   #打印False,因为未执行 start()来使ta线程运行  
    10.     ta.start()  
    11.     print(ta.isAlive())   #打印Ture,因为ta线程运行了  
    12.     time.sleep(3)  
    13.     print(ta.isAlive())   #打印False,因为ta线程已经结束了  



    5. name属性和daemon属性

    1.name属性表示线程的线程名 默认是 Thread-x  x是序号,由1开始,第一个创建的线程名字就是 Thread-1

    [python] view plain copy
    1. import threading  
    2. import time  
    3. class mythread(threading.Thread):  
    4.     def run(self):  
    5.         pass  
    6.   
    7. if __name__ == '__main__':  
    8.     ta = mythread()     #实例化线程  
    9.     ta.name = 'thread-ta'  
    10.     tb = mythread()  
    11.     tb.start()  
    12.     ta.start()  
    13.   
    14.     print(ta.name)  #打印 thread-ta  
    15.     print(tb.name)  #打印 Thread-2  



    view plain copy

    1. import threading  
    2. import time  
    3. class mythread(threading.Thread):  
    4.     def run(self):  
    5.         time.sleep(2)  
    6.         print('my thread over')  
    7.   
    8. def main():  
    9.     ta = mythread()  
    10.     ta.daemon = True  
    11.     ta.start()  
    12.     print('main thread over')  
    13.   
    14. if __name__ == '__main__':  
    15.     main()  
    16. #打印结果 :main thread over   然后马上结束程序  



    6.线程的同步---锁
    当一个进程拥有多个线程之后,如果他们各做各的任务互没有关系还行,但既然属于同一个进程,他们之间总是具有一定关系的。比如多个线程都要对某个数据进行修改,则可能会出现不可预料的结果。为保证操作正确,就需要引入锁来进行线程间的同步。

    python3 中的 threading 模块提供了 RLock锁(可重入锁)。对于某一时间只能让一个线程操作的语句放到 RLock的acquire 方法 和 release方法之间。即 acquire()方法相当于给RLock 锁  上锁,而 release() 相当于解锁。

    [python] view plain copy
    1. import threading  
    2. import time  
    3.   
    4. class mythread(threading.Thread):  
    5.     def run(self):  
    6.         global x            #声明一个全局变量  
    7.         lock.acquire()      #上锁,acquire()和release()之间的语句一次只能有一个线程进入,其余线程在acquire()处等待  
    8.         x += 10  
    9.         print('%s:%d'%(self.name,x))  
    10.         lock.release()      #解锁  
    11.   
    12. x = 0  
    13. lock = threading.RLock()    #创建 可重入锁  
    14. def main():  
    15.     l = []  
    16.     for i in range(5):  
    17.         l.append(mythread())    #创建 5 个线程,并把他们放到一个列表中  
    18.     for i in l:  
    19.         i.start()               #开启列表中的所有线程  
    20.   
    21. if __name__ =='__main__':  
    22.     main()  

    打印结果:

    Thread-1:10
    Thread-2:20
    Thread-3:30
    Thread-4:40
    Thread-5:50



    7.线程的同步---Event对象
    Event对象存在于 threading 模块中。Event 实例管理着 一个内部标志,通过 set() 方法来将该标志设置成 True,使用 clear() 方法将该标志重置成 False

    wait() 方法会使当前线程阻塞直到标志被设置成 True,wait()可以选择给他一个参数,代表时间,代表阻塞多长时间,若不设置就是阻塞直到标志被设置为True

    isSet()方法  :能判断标志位是否被设置为True

    [python] view plain copy
    1. import threading  
    2. import time  
    3.   
    4. class Mon(threading.Thread):  
    5.     def run(self):  
    6.         Dinner.clear()  
    7.         print('Cooking dinner')  
    8.         time.sleep(3)  
    9.         Dinner.set()    #标志设置为True  
    10.         print(self.name,':dinner is OK!')  
    11.   
    12. class Son(threading.Thread):  
    13.     def run(self):  
    14.         while True:  
    15.             if Dinner.isSet():  #判断标志位是否被设置为True  
    16.                 break  
    17.             else:  
    18.                 print('dinner isnot ready!')  
    19.                 Dinner.wait(1)  
    20.   
    21.         print(self.name,':Eating Dinner')  
    22.   
    23. def main():  
    24.     mon = Mon()  
    25.     son = Son()  
    26.     mon.name = 'Mon'  
    27.     son.name = 'Son'  
    28.     mon.start()  
    29.     son.start()  
    30.   
    31. if __name__ == '__main__':  
    32.     Dinner = threading.Event()  
    33.     main()  
    34.   
    35. ''''' 
    36. Cooking dinner 
    37. dinner isnot ready! 
    38. dinner isnot ready! 
    39. dinner isnot ready! 
    40. Mon :dinner is OK! 
    41. Son :Eating Dinner 
    42. '''  



    注意,这里的wait()跟上面Event提到的wait()不是同一样东西

    notify() 发出资源可用的信号,唤醒任意一条因 wait()阻塞的进程

    notifyAll() 发出资源可用信号,唤醒所有因wait()阻塞的进程

    下面给出一个例子,一家蛋糕店:只会做一个蛋糕,卖出后才会再做一个。绝对不会做积累到2个蛋糕。

    [python] view plain copy
      1. import threading  
      2. import time  
      3.   
      4. class Server(threading.Thread):  
      5.     def run(self):  
      6.         global x  
      7.         while True:  
      8.             con.acquire()  
      9.             while x>0:  
      10.                 con.wait()  
      11.             x += 1  
      12.             time.sleep(1)  
      13.             print(self.name,':I make %d cake!'%(x))  
      14.             con.notifyAll()  
      15.             con.release()  
      16.   
      17. class Client(threading.Thread):  
      18.     def run(self):  
      19.         global x  
      20.         con.acquire()  
      21.         while x == 0:  
      22.             con.wait()  
      23.         x-=1  
      24.         print(self.name,'I bought a cake! the rest is %d cake'%(x))  
      25.         con.notifyAll()  
      26.         con.release()  
      27.   
      28. def main():  
      29.     ser = Server()  
      30.     ser.name = 'Cake Server'  
      31.     client = []  
      32.     for i in range(3):  
      33.         client.append(Client())  
      34.     ser.start()  
      35.     for c in client:  
      36.         c.start()  
      37.   
      38. if __name__ =='__main__':  
      39.     x = 0  
      40.     con = threading.Condition()  
      41.     main()  
      42. ''''' 
      43. 打印结果: 
      44. Cake Server :I make 1 cake! 
      45. Thread-3 I bought a cake! the rest is 0 cake 
      46. Cake Server :I make 1 cake! 
      47. Thread-4 I bought a cake! the rest is 0 cake 
      48. Cake Server :I make 1 cake! 
      49. Thread-2 I bought a cake! the rest is 0 cake 
      50. Cake Server :I make 1 cake! 
      51. ''' 
  • 相关阅读:
    欢迎来怼--第二十三次Scrum会议
    作业要求 20171102 每周例行报告
    小程序中添加快递查询
    微信小程序——获取用户unionId
    nodejs开发 过程中express路由与中间件的理解
    nodejs 学习心得
    js中小知识记录
    TypeError: db.collection is not a function
    MONGODB安装教程
    CSS设置DIV背景色渐变显示--针对不同浏览器,背景渐变的兼容问问题
  • 原文地址:https://www.cnblogs.com/nuomin/p/7889171.html
Copyright © 2011-2022 走看看