Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 什么时候应该在常规线程上使用asyncio,为什么?它能提高性能吗?_Python_Multithreading_Python Asyncio - Fatal编程技术网

Python 什么时候应该在常规线程上使用asyncio,为什么?它能提高性能吗?

Python 什么时候应该在常规线程上使用asyncio,为什么?它能提高性能吗?,python,multithreading,python-asyncio,Python,Multithreading,Python Asyncio,我对Python中的多线程有着相当基本的理解,甚至对asyncio有着更基本的理解 我目前正在编写一个基于Curses的小程序(最终将使用完整的GUI,但这是另一个故事),该程序在主线程中处理UI和用户IO,然后有两个其他守护进程线程(每个线程都有自己的queue/worker-method-that-get-things-from-a-queue): 一种观察者线程,用于观察基于时间的和有条件的(例如,发送到留言板、接收到的消息等)事件的发生,然后将所需任务放入 另一个(worker)守护进

我对Python中的多线程有着相当基本的理解,甚至对
asyncio
有着更基本的理解

我目前正在编写一个基于Curses的小程序(最终将使用完整的GUI,但这是另一个故事),该程序在主线程中处理UI和用户IO,然后有两个其他守护进程线程(每个线程都有自己的queue/worker-method-that-get-things-from-a-queue):

  • 一种
    观察者
    线程,用于观察基于时间的和有条件的(例如,发送到留言板、接收到的消息等)事件的发生,然后将所需任务放入
  • 另一个(
    worker
    )守护进程线程的队列,然后完成它们
所有三个线程都连续并发运行,这让我产生了一些问题:

  • 工作者
    线程的队列(或者更一般地说,任何线程的队列)为空时,是否应该停止它,直到is有事情要做,或者可以让它继续运行?当并发线程除了观察队列之外什么都不做时,它们会占用大量的处理能力吗
  • 这两个线程的队列应该合并吗?由于
    watcher
    线程持续运行单个方法,我猜
    worker
    线程将能够从
    watcher
    线程放入的单个队列中提取任务
  • 我不认为这有什么关系,因为我不是多处理的,但是这个设置是否受到Python的GIL(我相信它仍然存在于3.4中)的任何影响
  • watcher
    线程是否应该像这样连续运行?根据我的理解,如果我错了,请纠正我,
    asyncio
    应该用于基于事件的多线程处理,这似乎与我正在尝试的操作相关
  • 主线程基本上总是等待用户按键访问菜单的不同部分。这似乎是一种
    asyncio
    非常适合的情况,但我也不确定
谢谢

当工作线程的队列(或者更一般地说,任何线程的队列)为空时,它应该停止,直到is有事情要做,还是可以继续运行?当并发线程除了观察队列之外什么都不做时,它们会占用大量的处理能力吗

您应该只使用对
queue.get()
的阻塞调用。这将使线程在I/O上阻塞,这意味着GIL将被释放,并且不会使用任何处理能力(或者至少是非常小的处理能力)。不要在
while
循环中使用非阻塞get,因为这将需要更多的CPU唤醒

这两个线程的队列应该合并吗?由于watcher线程持续运行单个方法,我猜工作线程将能够从watcher线程放入的单个队列中提取任务

如果观察者所做的一切都是从一个队列中取出东西并立即将其放入另一个队列中,在那里它会被一个工作者消耗掉,那么这听起来像是不必要的开销——您也可以直接在工作者中消耗它。不过,我还不太清楚情况是否如此——观察者是从队列中消费,还是只是将项目放入队列中?如果它是从队列中消费的,那么谁将东西放入队列中

我不认为这有什么关系,因为我不是多处理的,但是这个设置是否受到Python的GIL(我相信它仍然存在于3.4中)的任何影响

是的,这受GIL的影响。一次只能有一个线程运行Python字节码,因此无法获得真正的并行性,除非线程运行I/O(这会释放GIL)。如果您的工作线程正在执行CPU绑定的活动,如果可能的话,您应该认真考虑通过“代码>多进程< /代码>在单独的进程中运行它。

观察线程是否应该像这样连续运行?据我所知,如果我错了,请纠正我,asyncio应该用于基于事件的多线程,这似乎与我正在尝试做的相关

很难说,因为我不知道“连续跑步”到底是什么意思。它一直在做什么?如果它将大部分时间花在睡眠或阻塞
队列上
,这没关系——这两种情况都会释放GIL。如果它一直在做实际工作,那就需要GIL,因此会降低应用程序中其他线程的性能(假设它们同时在做工作)
asyncio
是为I/O绑定的程序而设计的,因此可以使用异步I/O在单个线程中运行。听起来您的程序可能非常适合使用异步I/O,这取决于您的
工作人员正在做什么

主线程基本上总是等待用户按键访问菜单的不同部分这似乎是asyncio最适合的情况,但我也不确定

任何您主要等待I/O的程序都有可能适合
asyncio
——但前提是您能找到一个能让curses(或您最终选择的任何其他GUI库)很好地使用它的库。大多数GUI框架都有自己的事件循环,这将与
asyncio
冲突。您需要使用一个库,使GUI的事件循环能够与
asyncio
的事件循环很好地配合使用。您还需要确保可以找到应用程序使用的任何其他基于同步I/O的库(例如数据库驱动程序)的兼容版本

也就是说,从基于线程的程序切换到基于
asyncio
的程序,您不太可能看到任何性能改进。它很可能会表现得很好