python - 为什么延迟会改变正在运行的 QThread 数量?

标签 python multithreading pyqt pyqt5 sleep

以下示例程序使用 QThread 实例来运行队列中的作业。

from queue import Queue
from sys import argv
from threading import Lock
from time import sleep
from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QApplication

class Worker(QObject):
    finished = pyqtSignal()

    def __init__(self, number):
        super().__init__()
        self.number = number

    @pyqtSlot()
    def work(self):
        while True:
            job = queue.get()
            if job is None:
                self.finished.emit()
                return
            with lock:
                print('worker={} job={}'.format(self.number, job))
            sleep(1)

app = QApplication(argv)
lock = Lock()
queue = Queue()
threads = []
nthreads = 4
for ithread in range(nthreads):
    thread = QThread()
    worker = Worker(ithread + 1)
    worker.moveToThread(thread)
    thread.started.connect(worker.work)
    worker.finished.connect(thread.quit)
    thread.start()
    threads += [thread]
    #-----------
    sleep(1e-10)
    #-----------

for ijob in range(10):
    queue.put(ijob + 1)

for _ in range(nthreads):
    queue.put(None)
for thread in threads:
    thread.wait()

通过 sleep 调用(参见标记行),所有线程都按预期运行。输出:

worker=1 job=1
worker=2 job=2
worker=3 job=3
worker=4 job=4
[…]

如果没有调用,任意数量的线程正在运行。输出:

worker=4 job=1
worker=4 job=2
worker=4 job=3
worker=4 job=4
[…]

我已经使用 Python 3.6.2 中的 PyQt 5、其他版本、可变的 sleep 持续时间、不同的语句顺序和运行的事件循环对此进行了测试。

为什么sleep调用会改变正在运行的线程数?

最佳答案

前三个工作对象容易被垃圾回收,而第四个则作为全局变量保留。 sleep 只允许每个线程有足够的时间来调用其关联工作线程的 work 方法,这将使它们全部保持事件状态(因为这些方法运行时会阻塞 while 循环) 。如果没有sleep,前三个工作线程将立即被垃圾回收,只留下第四个来处理队列。如果工作线程保存在列表中(与线程相同的方式),您应该看到所有工作线程都被利用(无论是否处于 sleep 状态)。

为了证明这就是正在发生的事情,您可以将其添加到 Worker 类中:

class Worker(QObject)
    ...

    def __del__(self):
        print('deleted:', self.number)

关于python - 为什么延迟会改变正在运行的 QThread 数量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46501921/

相关文章:

pyqt - Python 3 和 PyQt 4 建议

python - 如何创建独立的非模态对话框

python - 从 PyQt 中的 QTableWidget 中删除水平网格线

python - 尝试理解Python中的Soundex算法

python stackdriver google 函数 webhook 监听器

python - sqlite 提交未使用 python 更新保存更改?

Python:将打印函数作为参数发送

java - 我应该如何设计我的线程,以便不需要实例化泛型?

python - 如何在 Python 中维护 1000 个阻塞的 TCP 连接?

java - 立即停止线程