python里并发执行协程时部分阻塞超时怎么办

Python016

python里并发执行协程时部分阻塞超时怎么办,第1张

碰到这种需求时不要惊慌,可以使用wait()里的timeout参数来设置等待时间,也就是从这个函数开始运行算起,如果时间到达协程没有执行完成,就可以不再等它们了,直接从wait()函数里返回,返回之后就可以判断那些没有执行成功的,可以把这些协程取消掉。例子如下

import asyncio

async def phase(i):

    print('in phase {}'.format(i))

    try:

        await asyncio.sleep(0.1 * i)

    except asyncio.CancelledError:

        print('phase {} canceled'.format(i))

        raise

    else:

        print('done with phase {}'.format(i))

        return 'phase {} result'.format(i)

async def main(num_phases):

    print('starting main')

    phases = [

        phase(i)

        for i in range(num_phases)

    ]

    print('waiting 0.1 for phases to complete')

    completed, pending = await asyncio.wait(phases, timeout=0.1)

    print('{} completed and {} pending'.format(

        len(completed), len(pending),

    ))

    # Cancel remaining tasks so they do not generate errors

    # as we exit without finishing them.

    if pending:

        print('canceling tasks')

        for t in pending:

            t.cancel()

    print('exiting main')

event_loop = asyncio.get_event_loop()

try:

    event_loop.run_until_complete(main(3))

finally:

    event_loop.close()

结果输出如下:

starting main

waiting 0.1 for phases to complete

in phase 0

in phase 2

in phase 1

done with phase 0

1 completed and 2 pending

canceling tasks

exiting main

phase 1 canceled

phase 2 canceled

python 线程 暂停, 恢复, 退出

我们都知道python中可以是threading模块实现多线程, 但是模块并没有提供暂停, 恢复和停止线程的方法, 一旦线程对象调用start方法后, 只能等到对应的方法函数运行完毕. 也就是说一旦start后, 线程就属于失控状态. 不过, 我们可以自己实现这些. 一般的方法就是循环地判断一个标志位, 一旦标志位到达到预定的值, 就退出循环. 这样就能做到退出线程了. 但暂停和恢复线程就有点难了, 我一直也不清除有什么好的方法, 直到我看到threading中Event对象的wait方法的描述时.

wait([timeout])

Block until the internal flag is true. If the internal flag is true on entry, return immediately. Otherwise, block until another thread calls set() to set the flag to true, or until the optional timeout occurs.

阻塞, 直到内部的标志位为True时. 如果在内部的标志位在进入时为True时, 立即返回. 否则, 阻塞直到其他线程调用set()方法将标准位设为True, 或者到达了可选的timeout时间.

When the timeout argument is present and not None, it should be a floating point number specifying a timeout for the operation in seconds (or fractions thereof).

This method returns the internal flag on exit, so it will always return True except if a timeout is given and the operation times out.

当给定了timeout参数且不为None, 它应该是一个浮点数,以秒为单位指定操作的超时(或是分数)。

此方法在退出时返回内部标志,因此除非给定了超时且操作超时,否则它将始终返回True。

Changed in version 2.7: Previously, the method always returned None.

2.7版本以前, 这个方法总会返回None.

<br>

利用wait的阻塞机制, 就能够实现暂停和恢复了, 再配合循环判断标识位, 就能实现退出了, 下面是代码示例:

#!/usr/bin/env python

# coding: utf-8

import threading

import time

class Job(threading.Thread):

def __init__(self, *args, **kwargs):

super(Job, self).__init__(*args, **kwargs)

self.__flag = threading.Event() # 用于暂停线程的标识

self.__flag.set()# 设置为True

self.__running = threading.Event() # 用于停止线程的标识

self.__running.set() # 将running设置为True

def run(self):

while self.__running.isSet():

self.__flag.wait() # 为True时立即返回, 为False时阻塞直到内部的标识位为True后返回

print time.time()

time.sleep(1)

def pause(self):

self.__flag.clear() # 设置为False, 让线程阻塞

def resume(self):

self.__flag.set() # 设置为True, 让线程停止阻塞

def stop(self):

self.__flag.set()# 将线程从暂停状态恢复, 如何已经暂停的话

self.__running.clear()# 设置为False

下面是测试代码:

a = Job()

a.start()

time.sleep(3)

a.pause()

time.sleep(3)

a.resume()

time.sleep(3)

a.pause()

time.sleep(2)

a.stop()

<br>

测试的结果:

这完成了暂停, 恢复和停止的功能. 但是这里有一个缺点: 无论是暂停还是停止, 都不是瞬时的, 必须等待run函数内部的运行到达标志位判断时才有效. 也就是说操作会滞后一次.

但是这有时也不一定是坏事. 如果run函数中涉及了文件操作或数据库操作等, 完整地运行一次后再退出, 反而能够执行剩余的资源释放操作的代码(例如各种close). 不会出现程序的文件操作符超出上限, 数据库连接未释放等尴尬的情况.

有很多的场景中的事情是同时进行的,比如开车的时候,手和脚共同来驾驶汽车,再比如唱歌跳舞也是同时进行的

结果:

• _thread

• threading(推荐使用)

结果:

threading.enumerate() 可查看当前正在运行的线程

结果:

结果:

结果:

结果: 出现资源竞争导致计算结果不正确

(1)当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制

(2)线程同步能够保证多个线程安全访问资源,最简单的同步机制是引入互斥锁

(3)互斥锁为资源引入一个状态: 锁定/非锁定

(4)某个线程要更爱共享数据时,先将其锁定,此时资源的状态为"锁定", 其他线程不能更改直到该线程释放资源,将资源状态变为"非锁定"

(5)互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性

结果: 计算正确

结果:卡住了

在线程间共享多个资源的时候,如果两个线程分别战友一部分资源且同时等待对方资源,就会造成死锁

(1)程序设计时避免(银行家算法)

(2)添加超时时间