我对Python中的多线程有相当基本的了解,甚至对asyncio
。
我目前正在编写一个基于Curses的小型程序(最终将使用完整的GUI,但这是另一个故事),该程序处理主线程中的UI和用户IO,然后有两个其他守护进程线程(每个线程都有自己的守护程序)排队/从队列中获取东西的方法):
watcher
线程,该线程监视基于时间的和有条件的(例如,张贴到留言板,收到的消息等)事件,然后将所需的任务放入...worker
)守护程序线程的队列将完成它们。这三个线程都连续并发运行,这使我想到了一些问题:
worker
线程的队列(或更普遍地说,任何线程的队列)为空时,应该停止它,直到再次执行某件事为止,还是可以保持连续运行?当并发线程除了观察队列之外什么都不做时,它们会占用大量处理能力吗?watcher
线程连续运行单个方法,因此我猜想该worker
线程将能够从watcher
线程放入的单个队列中提取任务。watcher
线程连续这样运行?据我了解,如果我错了,请纠正我,asyncio
应该用于基于事件的多线程,这似乎与我要执行的操作有关。asyncio
完美的情况,但是,我不确定。谢谢!
当工作线程的队列(或更普遍地说,任何线程的队列)为空时,是否应该停止它直到再次执行某项操作,还是可以让它连续运行?当并发线程除了观察队列之外什么都不做时,它们会占用大量处理能力吗?
您应该只使用对的阻止调用queue.get()
。这将使线程在I / O上处于阻塞状态,这意味着GIL将被释放,并且将不使用任何处理能力(或至少非常少量)。不要在while
循环中使用非阻塞获取,因为这将需要更多的CPU唤醒。
两个线程的队列应该合并吗?由于观察者线程正在连续运行单个方法,因此我想工作线程将能够从观察者线程放入的单个队列中提取任务。
如果观察者所做的只是将事情从一个队列中拉出来,然后立即将其放入另一个队列中,由一个工作人员将其消耗掉,这听起来像是不必要的开销-您也可以直接在工作人员中消耗它。不过,对我来说还不是很清楚-观察者是从队列中消费,还是只是将项目放入一个队列中?如果是从队列中消费,是谁把东西进去?
我认为这并不重要,因为我不是多处理人员,但是此设置是否会以任何方式受到Python的GIL(我相信仍然存在于3.4中)的影响?
是的,这受GIL的影响。一次只有一个线程可以运行Python字节码,因此不会获得真正的并行性,除非线程正在运行I / O(释放GIL)。如果您的工作线程正在执行CPU绑定的活动,则应认真考虑multiprocessing
尽可能通过单独的进程运行它。
观察者线程是否应该像这样连续运行?据我了解,如果我错了,请纠正我,asyncio应该用于基于事件的多线程,这似乎与我要执行的操作有关。
很难说,因为我不完全了解“连续运行”的含义。它连续在做什么?如果它花费大部分时间在上睡眠或阻塞queue
,这很好-这两件事都会释放GIL。如果它一直在进行实际工作,那将需要GIL,因此会降低应用程序中其他线程的性能(假设它们试图同时工作)。asyncio
是为受I / O约束的程序而设计的,因此可以使用异步I / O 在单个线程中运行。听起来您的程序可能很适合此操作,具体取决于您worker
的工作。
主线程基本上总是只在等待用户按下键来访问菜单的不同部分。这似乎是asyncio的理想之选,但同样,我不确定。
任何您通常在等待I / O的程序都可能是一个好选择asyncio
-但前提是您能找到一个使curses发挥作用的库(或最终选择的任何其他GUI库)。大多数GUI框架都带有自己的事件循环,该事件循环将与冲突asyncio
。您将需要使用一个库,该库可以使GUI的事件循环与的事件循环完美配合asyncio
。您还需要确保可以找到asyncio
应用程序使用的任何其他基于同步I / O的库的兼容版本(例如,数据库驱动程序)。
就是说,从基于线程的程序切换到基于线程的程序,您不太可能看到任何形式的性能改进asyncio
。它的性能可能大致相同。由于您只处理3个线程,因此在它们之间进行上下文切换的开销不是很大,因此从该单线程异步I / O方法切换不会产生很大的不同。asyncio
可以帮助您避免线程同步的复杂性(如果这是您的应用程序存在的问题-尚不清楚),并且至少从理论上讲,如果您的应用程序可能需要大量线程,则可以更好地扩展,但是这似乎不是案件。我认为对您来说,基本上取决于您喜欢使用哪种样式编写代码(假设您可以找到所有asyncio
-您需要的兼容库)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句