Python之多线程

信号量

  信号量用来控制线程并发数的,BoundedSemaphore或Semaphore管理一个内置的计数 器,每当调用acquire()时-1,调用release()时+1。

       计数器不能小于0,当计数器为 0时,acquire()将阻塞线程至同步锁定状态,直到其他线程调用release()。(类似于停车位的概念)

       BoundedSemaphore与Semaphore的唯一区别在于前者将在调用release()时检查计数 器的值是否超过了计数器的初始值,如果超过了将抛出一个异常。

 1 import threading,time
 2 class myThread(threading.Thread):
 3     def run(self):
 4         if semaphore.acquire():
 5             print(self.name)
 6             time.sleep(5)
 7             semaphore.release()
 8 if __name__=="__main__":
 9     semaphore=threading.Semaphore(5) //计数器为5
10     thrs=[]
11     for i in range(100):
12         thrs.append(myThread())
13     for t in thrs:
14         t.start()
15 //执行结果:每五秒打印出5条线程名字
View Code

 条件变量同步

  有一类线程需要满足条件之后才能够继续执行,Python提供了threading.Condition 对象用于条件变量线程的支持,它除了能提供RLock()或Lock()的方法外,还提供了 wait()、  notify()、notifyAll()方法。

       lock_con=threading.Condition([Lock/Rlock]): 锁是可选选项,默认RLock,建议默认,RLock具备Lock功能

wait():条件不满足时调用,线程会释放锁并进入等待阻塞;
notify():条件创造后调用,通知等待池激活一个线程;
notifyAll():条件创造后调用,通知等待池激活所有线程。
 1 import threading,time
 2 from random import randint
 3 class Producer(threading.Thread):
 4     def run(self):
 5         global L
 6         val=randint(0,100)
 7         print('生产者',self.name,":Append"+str(val),L)
 8         if lock_con.acquire():
 9              L.append(val)
10              lock_con.notify() //通知等待池激活一个线程
11              lock_con.release()
12 class Consumer(threading.Thread):
13     def run(self):
14         global L
15         lock_con.acquire() //被激活的线程不会从阻塞代码行运行,而是从新获取锁运行
16             if len(L)==0:
17                 lock_con.wait()  //释放锁进入阻塞状态,进入等待池的等待激活
18             print('消费者',self.name,":Delete"+str(L[0]),L)
19             del L[0]
20             lock_con.release()
21 
22 if __name__=="__main__":
23 
24     L=[]
25     lock_con=threading.Condition()
26     threads=[]
27     for i in range(5):
28         threads.append(Producer())
29     threads.append(Consumer())
30     for t in threads:
31         t.start()
32     for t in threads:
33         t.join()
View Code

 同步条件

  同步条件和条件变量同步都具有通信功能,只是少了锁功能,当条件同步设计于不访问共享资源的条件环境时可以使用同步条件。event=threading.Event():条件环境对象,event内部具有一个布尔类的状态值,初始值 为False。

 

event.isSet():返回event当前状态值;

event.wait():此时event状态值为False,线程被阻塞;

event.set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度;

event.clear():恢复event的状态值为False。

 

 1 import threading,time
 2 class Boss(threading.Thread):
 3     def run(self):
 4         print("BOSS:今晚大家都要加班到22:00。") // 2:打印
 5         event.isSet() or event.set() // 3:判断event当前状态值并将event状态值设置为True,激活阻塞池中的线程
 6         time.sleep(5) // 4:等待5秒
 7         print("BOSS:<22:00>可以下班了。") // 9:打印
 8         event.isSet() or event.set() // 10:判断event当前状态值并将event状态值设置为True,激活阻塞池中的线程
 9 class Worker(threading.Thread):
10     def run(self):
11         event.wait() // 1:event 状态值为False,线程阻塞
12         print("Worker:哎……命苦啊!") // 5:打印
13         time.sleep(0.25) // 6:等待0.25秒
14         event.clear() // 7:恢复event状态值设为False
15         event.wait() // 8:线程阻塞
16         print("Worker:OhYeah!") // 11:打印
17 if __name__=="__main__":
18     event=threading.Event()
19     threads=[]
20     for i in range(5):
21         threads.append(Worker())
22     threads.append(Boss())
23     for t in threads:
24         t.start()
25     for t in threads:
26         t.join()
27 
28 //执行结果
29 BOSS:今晚大家都要加班到22:0030 Worker:哎……命苦啊!
31 Worker:哎……命苦啊!
32 Worker:哎……命苦啊!
33 Worker:哎……命苦啊!
34 Worker:哎……命苦啊!
35 BOSS:<22:00>可以下班了。
36 Worker:OhYeah!
37 Worker:OhYeah!
38 Worker:OhYeah!
39 Worker:OhYeah!
40 Worker:OhYeah!
View Code

 多线程利器-队列(queue)(重点)

  创建一个“队列”对象
  import Queue
  q = Queue.Queue([maxsize])
  Queue.Queue类即是一个队列的同步实现。队列长度可为无限或者有限。可通过Queue的构造函数的可选参数maxsize来设定队列长度。如果maxsize为0就表示队列长度无限,默认为0。

    将一个值放入队列中
  q.put(item, [block])
  调用队列对象的put()方法在队列末尾追加一个项目。put()有两个参数,第一个item为必需的,为插入项目的值;第二个block为可选参数,默认为
  1。当一个队列长度为10,并且已经put进10个元素,如果再put第11个元素,此时则取决put第11个元素时block的值,如果block为1,则程序在这一行进入阻塞状态;如果block为0,则程序终止执行,并抛出Full异常。

    将一个值从队列中取出
  q.get()
  调用队列对象的get()方法从队列起始位置删除并返回一个项目。可选参数为block,与put()方法的block参数相同,block参数默认为1。当队列为空时,如果block为1,则程序在这一行进入阻塞状态;如果block为0,则程序终止执行,并抛出empty异常。

Python Queue模块有三种队列及构造函数(后两种不常使用):
1、Python Queue模块的FIFO队列先进先出。  class queue.Queue(maxsize)
2、LIFO类似于堆,即先进后出。             class queue.LifoQueue(maxsize)
3、还有一种是优先级队列级别越低越先出来。   class queue.PriorityQueue(maxsize)

queque模块中的常用方法(q = queue.Queue()):

q.qsize() 返回队列的大小
q.empty() 如果队列为空,返回True,反之False
q.full() 如果队列满了,返回True,反之False
q.full 与 maxsize 大小对应
q.get([block[, timeout]]) 获取队列,timeout等待时间
q.get_nowait() 相当q.get(False)
非阻塞 q.put(item) 写入队列,timeout等待时间
q.put_nowait(item) 相当q.put(item, False)
q.task_done() 在完成一项工作之后,q.task_done() 函数向任务已经完成的队列发送一个信号
q.join() 实际上意味着等到队列为空,再执行别的操作

队列的优点就是多个线程操作队列时,不会出现数据混乱的可能,这是因为在队列内部对这段数据加了锁,所以当多个线程需要操作同一份数据时,我们可以使用队列。

 1 import threading, queue, random
 2 
 3 class Producer(threading.Thread):
 4 
 5     def run(self):
 6         val = random.randint(0, 100)
 7         q.put(val)
 8         print('生产者生产了%s台电脑'%val)
 9 
10 class Consumer(threading.Thread):
11 
12     def run(self):
13         while True:
14             try:
15                 print('批发商买走%s台电脑'%q.get(0))
16             except Exception:
17                 break
18 
19 q = queue.Queue()
20 
21 threading = [Producer(), Producer(), Producer(), Consumer()]
22 for t in threading:
23     t.start()
24 
25 //执行结果
26 生产者生产了98台电脑
27 生产者生产了40台电脑
28 生产者生产了44台电脑
29 批发商买走98台电脑
30 批发商买走40台电脑
31 批发商买走44台电脑
View Code

 

转载于:https://www.cnblogs.com/jianguozhang/p/8536881.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值