Event对象
线程的一个关键特性是每个线程都是独立运行且状态不可预测。如果程序中的其 他线程需要通过判断某个线程的状态来确定自己下一步的操作,这时线程同步问题就 会变得非常棘手。为了解决这些问题,我们需要使用threading库中的Event对象。 对象包含一个可由线程设置的信号标志,它允许线程等待某些事件的发生。在 初始情况下,Event对象中的信号标志被设置为假。如果有线程等待一个Event对象, 而这个Event对象的标志为假,那么这个线程将会被一直阻塞直至该标志为真。一个线程如果将一个Event对象的信号标志设置为真,它将唤醒所有等待这个Event对象的线程。如果一个线程等待一个已经被设置为真的Event对象,那么它将忽略这个事件, 继续执行。
event.isSet():返回event的状态值;
event.wait():如果 event.isSet()==False将阻塞线程;
event.set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度;
event.clear():恢复event的状态值为False。
# import threading,time
#
# event=threading.Event()#实例化一个Event对象
#
# def foo():
# while not event.isSet():#判断状态
# print('wait....')
# event.wait(2)#等2秒 不写秒数 ,默认一直等到状态为True 才继续执行
# print('longin server')
# for i in range(3):
# t=threading.Thread(target=foo)
# t.start()
#
# print('start server')
# time.sleep(5)
# event.set()#修改状态为True
=================================================================
队列(queue)当信息必须在多个线程之间安全交换时,队列在线程编程中特别有用。
class queue.Queue(maxsize=0) #先进先出 可以设置队列最大长度:直接在括号里写数字
class queue.LifoQueue(maxsize=0) #先进后出 可以设置队列最大长度
class queue.PriorityQueue(maxsize=0) #存储数据时可设置优先级的队列 可以设置队列最大长度
import queue,threading q=queue.Queue()#实例化一个queue对象 #先进先出 def p(): q.put("first")#向队列里放数据 q.put('second') q.put('third') def g(): print(q.get())#从队列中取数据 #first
#third print(q.get())t1=threading.Thread(target=p,args=())t2=threading.Thread(target=g,args=())t1.start()t2.start()print(q.get()) #second
import queue,threading
q=queue.LifoQueue()#先进后出
def p():
q.put("first")
q.put('second')
q.put('third')
def g():
print(q.get()) #third
print(q.get()) #second
print(q.get()) #first
t1=threading.Thread(target=p,args=())
t2=threading.Thread(target=g,args=())
t1.start()
t2.start()
import queue,threading
q=queue.PriorityQueue()#优先级
def p():
q.put((2,"first"))
q.put((1,'second'))
q.put((3,'third'))
def g():
print(q.get()) #(1, 'second')
print(q.get()) #(2, 'first')
print(q.get()) #(3, 'third')
t1=threading.Thread(target=p,args=())
t2=threading.Thread(target=g,args=())
t1.start()
t2.start()
-------------------------------------------------------------------------------------------------------------------
join与task_done方法
import queue,threading
q=queue.PriorityQueue()
def p():
q.put((2,"first"))
q.put((1,'second'))
q.put((3,'third'))
q.join()#阻塞,等待计数器(put几次计数器加几)归零后 继续执行
print('ok')
def g():
print(q.get())
q.task_done()#计数器减一
print(q.get())
q.task_done()#计数器减一
print(q.get())
q.task_done()#计数器减一
t1=threading.Thread(target=p,args=())
t2=threading.Thread(target=g,args=())
t1.start()
t2.start()
-------------------------------------------------------------------------------------------------------------------
此包中的常用方法(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() 实际上意味着等到队列为空,再执行别的操作
=================================================================
生产者消费者模型
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。
为什么要使用生产者和消费者模式
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
什么是生产者消费者模式
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
# import threading,queue,time,random
#
# q=queue.Queue(50)
#
# def Producer():
# count=1
# while count<10:
# if q.qsize() <20:
# s=random.randint(1,100)
# q.put(s)
# print('has made baozi {}'.format(s))
# time.sleep(1)
# count+=1
# def Consumer(id):
# while 1:
# s=q.get()
# print('Consumer'+id+'has eat %s'%s)
# time.sleep(2)
#
# for i in range(50):
# t1=threading.Thread(target=Producer,args=())
# t1.start()
# for i in range(10):
# t=threading.Thread(target=Consumer,args=(str(i),))
# t.start()
=================================================================
多进程
由于GIL的存在,python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程。
multiprocessing包是Python中的多进程管理包。与threading.Thread类似,它可以利用multiprocessing.Process对象来创建一个进程。该进程可以运行在Python程序内部编写的函数。该Process对象与Thread对象的用法相同,也有start(), run(), join()的方法。此外multiprocessing包中也有Lock/Event/Semaphore/Condition类 (这些对象可以像多线程那样,通过参数传递给各个进程),用以同步进程,其用法与threading包中的同名类一致。所以,multiprocessing的很大一部份与threading使用同一套API,只不过换到了多进程的情境。
import multiprocessing,time
def foo(n):
print(2**n)
def bar(n):
print(3**n)
if __name__ == '__main__':
s=time.time()
p1=multiprocessing.Process(target=foo,args=(2222222,))#实例化创建一个进程
p2=multiprocessing.Process(target=bar,args=(2222222,))
p1.start()#开始执行
p2.start()
p1.join()#等待p1执行结束
p2.join()
# foo(2222222)
# bar(2222222)
print(time.time()-s)