继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

python3 多线程编程

潇潇雨雨
关注TA
已关注
手记 165
粉丝 25
获赞 128

0.什么是线程

  1. 多线程模块

  2. 创建线程的方法

  3. join()方法

4.isAlive()方法

  1. name属性和daemon属性

6.线程的同步---锁

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

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

0.什么是线程

线程是CPU分配资源的基本单位。但一个程序开始运行,这个程序就变成了一个进程,而一个进程相当于一个或者多个线程。当没有多线程编程时,一个进程也是一个主线程,但有多线程编程时,一个进程包含多个线程,包括主线程。使用线程可以实现程序的并发。

  1. 多线程模块

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

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

  1. 创建线程的方法

1.用 thread.Thread 直接在线程中运行函数

[python] view plain copy

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

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

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

[python] view plain copy

import threading  class mythread(threading.Thread):      def run(self):          for i in range(1,5):              print(i)  ma = mythread();  mb = mythread();  ma.start()  mb.start()
  1. join()方法

join()作用是 调用 join() 的线程 阻塞直到 某一线程结束才继续执行

[python] view plain copy

import threading  import time  class mythread(threading.Thread):      def run(self):          self.i = 1          print('%d'%(self.i))          self.i = self.i+1          time.sleep(1)           #睡眠一秒          print('%d'%(self.i))          time.sleep(1)  if __name__ == '__main__':      ta = mythread()     #实例化线程      ta.start()          #开启ta线程      ta.join()           #主线程等待 ta线程结束才继续执行      print('main thread over')

4.isAlive()方法

这个方法用于判断线程是否运行。

1.当线程未调用 start()来开启时,isAlive()会返回False

2.但线程已经执行后并结束时,isAlive()也会返回False

[python] view plain copy

import threading  import time  class mythread(threading.Thread):      def run(self):         time.sleep(2)  if __name__ == '__main__':      ta = mythread()     #实例化线程      print(ta.isAlive())   #打印False,因为未执行 start()来使ta线程运行      ta.start()      print(ta.isAlive())   #打印Ture,因为ta线程运行了      time.sleep(3)      print(ta.isAlive())   #打印False,因为ta线程已经结束了
  1. name属性和daemon属性

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

[python] view plain copy

import threading  import time  class mythread(threading.Thread):      def run(self):          pass  if __name__ == '__main__':      ta = mythread()     #实例化线程      ta.name = 'thread-ta'      tb = mythread()      tb.start()      ta.start()      print(ta.name)  #打印 thread-ta      print(tb.name)  #打印 Thread-2

2.daemon属性用来设置线程是否随主线程退出而退出

当 daemon = False 时,线程不会随主线程退出而退出(默认时,就是 daemon = False)

当 daemon = True 时,当主线程结束,其他子线程就会被强制结束

[python] view plain copy

import threading  import time  class mythread(threading.Thread):      def run(self):          time.sleep(2)          print('my thread over')  def main():      ta = mythread()      ta.daemon = True      ta.start()      print('main thread over')  if __name__ == '__main__':      main()  #打印结果 :main thread over   然后马上结束程序

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

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

[python] view plain copy

import threading  import time  class mythread(threading.Thread):      def run(self):          global x            #声明一个全局变量          lock.acquire()      #上锁,acquire()和release()之间的语句一次只能有一个线程进入,其余线程在acquire()处等待          x += 10          print('%s:%d'%(self.name,x))          lock.release()      #解锁  x = 0  lock = threading.RLock()    #创建 可重入锁  def main():      l = []      for i in range(5):          l.append(mythread())    #创建 5 个线程,并把他们放到一个列表中      for i in l:          i.start()               #开启列表中的所有线程  if __name__ =='__main__':      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

import threading  import time  class Mon(threading.Thread):      def run(self):          Dinner.clear()          print('Cooking dinner')          time.sleep(3)          Dinner.set()    #标志设置为True          print(self.name,':dinner is OK!')  class Son(threading.Thread):      def run(self):          while True:              if Dinner.isSet():  #判断标志位是否被设置为True                  break              else:                  print('dinner isnot ready!')                  Dinner.wait(1)          print(self.name,':Eating Dinner')  def main():      mon = Mon()      son = Son()      mon.name = 'Mon'      son.name = 'Son'      mon.start()      son.start()  if __name__ == '__main__':      Dinner = threading.Event()      main()  ''''' Cooking dinner dinner isnot ready! dinner isnot ready! dinner isnot ready! Mon :dinner is OK! Son :Eating Dinner '''

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

条件变量表示当线程满足某一个 条件才被唤醒,否则一直阻塞

对比 只用锁不用条件变量 的好处就是:只用锁的话,如果一个线程在上锁后,解锁前,因为某一条件一直阻塞着,那么锁就一直解不开,那么其他线程也就因为一直获取不了锁而跟着阻塞着,这样效率就不好,浪费了很多时间。对于这种情况,锁+条件变量可以让该线程先 解锁,然后阻塞着,等待条件满足了,再重新唤醒并获取锁(上锁)。这样就不会因为一个线程阻塞着而影响其他线程也跟着阻塞了。

Condition 提供的方法:

acquire() 和 release() 表示上锁和解锁,和 单纯的锁机制一样。

wait()  解开锁,阻塞,直到其他线程调用了notify()或者notifyAll才被唤醒,注意,这里的wait()跟上面Event提到的wait()不是同一样东西

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

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

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

[python] view plain copy

import threading  import time  class Server(threading.Thread):      
def run(self):          
global x          
while True:              
con.acquire()              
while x>0:                  
con.wait()              
x += 1              
time.sleep(1)              
print(self.name,':I make %d cake!'%(x))              
con.notifyAll()              
con.release()  class Client(threading.Thread):      
def run(self):          
global x          
con.acquire()          
while x == 0:              
con.wait()          
x-=1          
print(self.name,'I bought a cake! the rest is %d cake'%(x))          
con.notifyAll()          
con.release()  def main():      
ser = Server()      
ser.name = 'Cake Server'      
client = []      
for i in range(3):          
client.append(Client())      
ser.start()      
for c in client:          
c.start()  if __name__ =='__main__':      
x = 0      
con = threading.Condition()      
main()  ''''' 打印结果: Cake Server :I make 1 cake! Thread-3 I bought a cake! the rest is 0 cake Cake Server :I make 1 cake! Thread-4 I bought a cake! the rest is 0 cake Cake Server :I make 1 cake! Thread-2 I bought a cake! the rest is 0 cake Cake Server :I make 1 cake! '''

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP