Python–cookbook–12.并发编程

Python–cookbook–12.并发编程

相关介绍

# coding=utf8
import time
from threading import Thread, Event, Condition, Semaphore
import multiprocessing
from queue import Queue
import heapq

# 并发执行的代码创建/销毁线程
def countdown(n):
    while n > 0:
        print('T-minus', n)
        n -= 1
        time.sleep(5)
# t = Thread(target=countdown, args=(3,))
# 对于需要长时间运行的线程或者需要一直运行的后台任务,你应当考虑使用后台线程
# t = Thread(target=countdown, args=(3,), daemon=True)  # 后台线程
# t.start()  # 开始执行
# if t.is_alive():
#     print('Still running')
# else:
#     print('Completed')

# 无法结束一个线程,无法给它发送信号,无法调整它的调度,也无法执行其他高级操作
# 你需要终止线程,那么这个线程必须通过编程在某个特定点轮询来退出
class CountdownTask:
    def __init__(self):
        self._running = True
    def terminate(self):
        self._running = False
    def run(self, n):
        while self._running and n > 0:
            print('T-minus', n)
            n -= 1
            time.sleep(5)
# c = CountdownTask()
# t = Thread(target=c.run, args=(3,))
# t.start()
# c.terminate() # Signal termination
# t.join() # Wait for actual termination (if needed)
# 由于全局解释锁(GIL)的原因,Python 的线程被限制到同一时刻只允许一个线
# 程执行这样一个执行模型。所以,Python 的线程更适用于处理 I/O 和其他需要并发执
# 行的阻塞操作(比如等待 I/O、等待从数据库获取数据等等),而不是需要多处理器并
# 行的计算密集型任务。


# event.isSet():返回event的状态值;
# event.wait():如果 event.isSet()==False将阻塞线程;
# event.set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度;
# event.clear():恢复event的状态值为False。
# 判断线程是否已经启动
def countdown2(n, started_evt):
    print('countdown starting')
    started_evt.set()
    while n > 0:
        print('T-minus', n)
        n -= 1
        time.sleep(2)
# started_evt = Event()
# print('Launching countdown')
# t = Thread(target=countdown2, args=(5, started_evt))
# t.start()
# started_evt.wait()
# print('countdown is running')
# # “countdown is running”总是显示在“countdown starting”之后显示

# 如果一个线程需要不停地重复使用 event 对象,你最好使用 Condition 对象来代替
# wait :等待条件通知
# wait_for:等待某个条件的通知
# notify :唤醒一个或多个正在等待的condtion
# notify_all:唤醒所有正在等待的condtion
class PeriodicTimer:
    def __init__(self, interval):
        self._interval = interval
        self._flag = 0
        self._cv = Condition()
    def start(self):
        t = Thread(target=self.run)
        t.daemon = True
        t.start()
    def run(self):
        while True:
            time.sleep(self._interval)
            with self._cv:
                self._flag ^= 1
                self._cv.notify_all()
    def wait_for_tick(self):
        with self._cv:
            last_flag = self._flag
            while last_flag == self._flag:
                self._cv.wait()
ptimer = PeriodicTimer(1)
ptimer.start()
def countdown3(nticks):
    while nticks > 0:
        ptimer.wait_for_tick()
        print('countdown3', nticks)
        nticks -= 1
def countup(last):
    n = 0
    while n < last:
        ptimer.wait_for_tick()
        print('countup', n)
        n += 1
Thread(target=countdown3, args=(10,)).start()
Thread(target=countup, args=(5,)).start()

# 使用信号量实现
# def worker(n, sema):
#     sema.acquire()
#     print('Working', n)
# sema = Semaphore(0)
# nworkers = 10
# for n in range(nworkers):
#     t = Thread(target=worker, args=(n, sema,))
#     t.start()
# sema.release()

# 线程间通信
_sentinel = object()  # 用来关闭,终止执行
def producer(out_q):
    while True:
        # ... 产生数据
        data = 1
        out_q.put(data)
        break
    out_q.put(_sentinel)
def consumer(in_q):
    while True:
        data = in_q.get()
        # 运行数据 ...
        if data is _sentinel:
            in_q.put(_sentinel)
            break
# # Create the shared queue and launch both threads
# q = Queue()
# t1 = Thread(target=consumer, args=(q,))
# t2 = Thread(target=producer, args=(q,))
# t1.start()
# t2.start()

# 线程安全的优先级队列
class PriorityQueue:
    def __init__(self):
        self._queue = []
        self._count = 0
        self._cv = Condition()
    def put(self, item, priority):
        with self._cv:
            heapq.heappush(self._queue, (-priority, self._count, item))
            self._count += 1
            self._cv.notify()
    def get(self):
        with self._cv:
            while len(self._queue) == 0:
                self._cv.wait()
            return heapq.heappop(self._queue)[-1]

# 给关键部分加锁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柴寺仓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值