python 线程(2)-- 线程通信event,queue

一.Event

如果程序中的其他线程需要通过判断某个线程的状态来确定自己下一步的操作,这时候就可以用threading为我们提供的Event对象,Event对象主要有一下几个方法:

  isSet():返回event的状态值;

  wait():如果 event==False 将阻塞当前线程;

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

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

  有如下需求:获取当前时间的秒数的个位数,如果小于5,设置子线程阻塞,如果大于5则设置子进程非阻塞。代码如下:

from threading import Event, Thread

import time

from datetime import datetime

def func(e):

    print('子线程:开始运行……')

    while True:

        print('子线程:现在事件秒数是{}'.format(datetime.now().second))

        e.wait()  # 阻塞等待信号  这里插入了一个Flag  默认为 False

        time.sleep(1)

e = Event()

p = Thread(target=func, args=(e,))

p.daemon=True

p.start()

for i in range(10):

    s = int(str(datetime.now().second)[-1])#获取当前秒数的个位数

    if s < 5:

        print('子线程线入阻塞状态')

        e.clear()  # 使插入的flag为False 线程线入阻塞状态

    else:

        print('子线程取消阻塞状态')

        e.set()  # 线程线入非阻塞状态

    time.sleep(1)

e.set()

print("主线程运行结束……")
>>>
 输出结果:

  子线程:开始运行……

  子线程:现在事件秒数是43

  子线程线入阻塞状态

  子线程线入阻塞状态

  子线程取消阻塞状态

  子线程取消阻塞状态

  子线程:现在事件秒数是46

  子线程取消阻塞状态

  子线程:现在事件秒数是47

  子线程取消阻塞状态

  子线程:现在事件秒数是48

  子线程取消阻塞状态

  子线程:现在事件秒数是49

  子线程线入阻塞状态

  子线程:现在事件秒数是50

  子线程线入阻塞状态

  子线程线入阻塞状态

  主线程运行结束……

二.queue (推荐使用)

python中Queue模块提供了队列都实现了锁原语,是线程安全的,能够在多线程中直接使用。Queue中的队列包括以下三种:

  1)FIFO(先进先出)队列, 第一加入队列的任务, 被第一个取出;

  2)LIFO(后进先出)队列,最后加入队列的任务, 被第一个取出;

  3)PriorityQueue(优先级)队列, 保持队列数据有序, 最小值被先取出。

  Queue模块中的常用方法如下:

  qsize() 返回队列的规模

  empty() 如果队列为空,返回True,否则False

  full() 如果队列满了,返回True,否则False

  get([block[, timeout]])获取队列,timeout等待时间

  get_nowait() 相当get(False)

  put(item) 写入队列,timeout等待时间,如果队列已满再调用该方法会阻塞线程

  put_nowait(item) 相当put(item, False)

  task_done() 在完成一项工作之后,task_done()函数向任务已经完成的队列发送一个信号

  join() 实际上意味着等到队列为空,再执行别的操作。

import queue

import threading

def fun():

    while True:

        try:

            data = q.get(block = True, timeout = 1) #不设置阻塞的话会一直去尝试获取资源

        except queue.Empty:

            print(' {}结束……'.format(threading.current_thread().name))

            break

        print(' {}取得数据:{}'.format(threading.current_thread().name , data))

        q.task_done()

        print(' {}结束……'.format(threading.current_thread().name))

print("主线程开始运行……")

q = queue.Queue(5)

#往队列里面放5个数

for i in range(5):

    q.put(i)

for i in range(0, 3):

    t = threading.Thread(target=fun , name='线程'+str(i))

    t.start()

q.join() #等待所有的队列资源都用完

print("主线程结束运行……")

》》》
输出结果:

  主线程开始运行……

  线程0取得数据:0

  线程0结束……

  线程0取得数据:1

  线程0结束……

  线程1取得数据:2

  线程0取得数据:3

  线程0结束……

  线程0取得数据:4

  线程0结束……

  线程1结束……

  主线程结束运行……

  线程1结束……

  线程2结束……

  线程0结束……

参考:

12.3 线程间通信 — python3-cookbook 3.0.0 文档

**python并发编程系列之多线程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值