wolong 发表于 2018-8-8 09:54:42

python3 多线程编程

  0.什么是线程


[*]  多线程模块

[*]  创建线程的方法

[*]join()方法
  4.isAlive()方法


[*]name属性和daemon属性
  6.线程的同步---锁
  7.线程的同步---Event对象
  8.线程的同步---Condition条件变量
  0.什么是线程
  线程是CPU分配资源的基本单位。但一个程序开始运行,这个程序就变成了一个进程,而一个进程相当于一个或者多个线程。当没有多线程编程时,一个进程也是一个主线程,但有多线程编程时,一个进程包含多个线程,包括主线程。使用线程可以实现程序的并发。


[*]多线程模块
  python3对多线程支持的是 threading 模块,应用这个模块可以创建多线程程序,并且在多线程间进行同步和通信。在python3 中,可以通过两种方法来创建线程:
  第一:通过 threading.Thread 直接在线程中运行函数;第二:通过继承 threading.Thread 类来创建线程


[*]创建线程的方法
  1.用 thread.Thread 直接在线程中运行函数
   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()开启线程就可以了
   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()
  


[*]join()方法
  join()作用是 调用 join() 的线程 阻塞直到 某一线程结束才继续执行
   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
   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线程已经结束了
  


[*]name属性和daemon属性
  1.name属性表示线程的线程名 默认是 Thread-xx是序号,由1开始,第一个创建的线程名字就是 Thread-1
   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 时,当主线程结束,其他子线程就会被强制结束
   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 方法 和>   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
   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() 和>  wait()解开锁,阻塞,直到其他线程调用了notify()或者notifyAll才被唤醒,注意,这里的wait()跟上面Event提到的wait()不是同一样东西
  notify() 发出资源可用的信号,唤醒任意一条因 wait()阻塞的进程
  notifyAll() 发出资源可用信号,唤醒所有因wait()阻塞的进程
  下面给出一个例子,一家蛋糕店:只会做一个蛋糕,卖出后才会再做一个。绝对不会做积累到2个蛋糕。
   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!
  
'''
页: [1]
查看完整版本: python3 多线程编程