Как работает приоритетность потоков? (QThread)

Как работает приоритетность потоков?
Должен ли 3 поток успевать суммировать больше, или это зависит от нагруженности функции run()?

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys
import time
import math

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(278, 152)
        self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
        self.verticalLayout.setObjectName("verticalLayout")
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setObjectName("gridLayout")
        self.label_2 = QtWidgets.QLabel(Dialog)
        self.label_2.setObjectName("label_2")
        self.gridLayout.addWidget(self.label_2, 0, 1, 1, 1)
        self.label_3 = QtWidgets.QLabel(Dialog)
        self.label_3.setObjectName("label_3")
        self.gridLayout.addWidget(self.label_3, 0, 2, 1, 1)
        self.label = QtWidgets.QLabel(Dialog)
        self.label.setObjectName("label")
        self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
        self.label_4 = QtWidgets.QLabel(Dialog)
        self.label_4.setText("")
        self.label_4.setObjectName("label_4")
        self.gridLayout.addWidget(self.label_4, 1, 0, 1, 1)
        self.label_5 = QtWidgets.QLabel(Dialog)
        self.label_5.setText("")
        self.label_5.setObjectName("label_5")
        self.gridLayout.addWidget(self.label_5, 1, 1, 1, 1)
        self.label_6 = QtWidgets.QLabel(Dialog)
        self.label_6.setText("")
        self.label_6.setObjectName("label_6")
        self.gridLayout.addWidget(self.label_6, 1, 2, 1, 1)
        self.verticalLayout.addLayout(self.gridLayout)

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
        self.label_2.setText(_translate("Dialog", "2 поток"))
        self.label_3.setText(_translate("Dialog", "3 поток"))
        self.label.setText(_translate("Dialog", "1 поток"))

class Thread(QThread):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._isPause = False
        self.condition = QWaitCondition()
        self.mutex = QMutex()
        self.sum = 0

    def run(self):
        while True:
            self.sum += 1


class Window(QDialog, Ui_Dialog):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.update)
        self.timer.start(2000)

        self.thread = Thread(self)
        self.thread.start(QThread.LowestPriority)
        print(self.thread.priority())
        self.thread_2 = Thread(self)
        self.thread_2.start(QThread.NormalPriority)
        print(self.thread_2.priority())
        self.thread_3 = Thread(self)
        self.thread_3.start(QThread.HighestPriority)
        print(self.thread_3.priority())


    def update(self):
        self.label_4.setText(str(self.thread.sum))
        self.label_5.setText(str(self.thread_2.sum))
        self.label_6.setText(str(self.thread_3.sum))


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

Ответы (1 шт):

Автор решения: S. Nick

Я не знаю правильно ли понял ваш вопрос, но обратите внимание на следующие моменты:

  1. Код запускает 3 потока с приоритетами, которые вы установили. Обратите внимание, что в этом варианте нет никакой задержки в работе потока(# self.msleep(1) -закомментировано ). Также обратите внимание на загрузку ЦП. Запуск двух таких приложений уложат интерфейс. Приоритеты работают как надо.

q1282746.py

import sys
from PyQt5 import QtCore, QtGui, QtWidgets


class Thread(QtCore.QThread):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._isPause = False
        self.condition = QtCore.QWaitCondition()
        self.mutex = QtCore.QMutex()
        self.sum = 0

    def run(self):
        while True:
            self.sum += 1
#            self.msleep(1)                                    # !!!


class Window(QtWidgets.QDialog): 
    def __init__(self):
        super().__init__()
        
        self.label_4 = QtWidgets.QLabel()
        self.label_5 = QtWidgets.QLabel()
        self.label_6 = QtWidgets.QLabel()
        self.label_sum = QtWidgets.QLabel()
        self.label_time = QtWidgets.QLabel('0')
        
        layout = QtWidgets.QFormLayout(self)
        layout.addRow(f'{"Низкий приоритет":>40}:', self.label_4)
        layout.addRow(f'{"Нормальный приоритет":>35}:', self.label_5)
        layout.addRow(f'{"чаще, чем Высокий приоритет":>30}:', self.label_6)
        layout.addRow("", self.label_sum)
        layout.addRow("", self.label_time)
         
        self.thread = Thread(self)
        self.thread.start(QtCore.QThread.LowestPriority)
        print(f'LowestPriority {self.thread.priority()}:')
        self.thread_2 = Thread(self)
        self.thread_2.start(QtCore.QThread.NormalPriority)
        print(f'NormalPriority {self.thread_2.priority()}:')
        self.thread_3 = Thread(self)
        self.thread_3.start(QtCore.QThread.HighestPriority)
        print(f'HighestPriority {self.thread_3.priority()}:')
        
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.update)
        self.timer.start(2000)

    def update(self):
        self.label_4.setText(f'{self.thread.sum:>20,}')
        self.label_5.setText(f'{self.thread_2.sum:>20,}')
        self.label_6.setText(f'{self.thread_3.sum:>20,}')
        self.label_sum.setText(f'{self.thread.sum + self.thread_2.sum + self.thread_3.sum:>20,}')
        
        self.label_time.setText(
            f'{str(int(self.label_time.text()) + 2):>26}'
        )
        if int(self.label_time.text()) == 102:
            self.timer.stop()

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    app.setFont(QtGui.QFont("Times", 12, QtGui.QFont.Bold))
    window = Window()
    window.resize(450, 152)
    window.show()
    sys.exit(app.exec_())

введите сюда описание изображения

  1. Код запускает с 1 потоком. Обратите внимание, что в этом варианте нет никакой задержки в работе потока(# self.msleep(1) -закомментировано ). Также обратите внимание на загрузку ЦП. Запуск двух таких приложений уложат интерфейс.

q1282746-222.py

import sys
from PyQt5 import QtCore, QtGui, QtWidgets


class Thread(QtCore.QThread):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._isPause = False
        self.condition = QtCore.QWaitCondition()
        self.mutex = QtCore.QMutex()
        self.sum = 0

    def run(self):
        while True:
            self.sum += 1
#            self.msleep(1)                                    # !!!


class Window(QtWidgets.QDialog): 
    def __init__(self):
        super().__init__()
        
        self.label_4 = QtWidgets.QLabel()
#        self.label_5 = QtWidgets.QLabel()
#        self.label_6 = QtWidgets.QLabel()
        self.label_time = QtWidgets.QLabel('0')
        
        layout = QtWidgets.QFormLayout(self)
        layout.addRow(f'{"Один поток":>40}:', self.label_4)
#        layout.addRow(f'{"Нормальный приоритет":>35}:', self.label_5)
#        layout.addRow(f'{"чаще, чем Высокий приоритет":>30}:', self.label_6)
        layout.addRow("", self.label_time)
         
        self.thread = Thread(self)
        self.thread.start()
        '''
        print(f'LowestPriority {self.thread.priority()}:')
        self.thread_2 = Thread(self)
        self.thread_2.start(QtCore.QThread.NormalPriority)
        print(f'NormalPriority {self.thread_2.priority()}:')
        self.thread_3 = Thread(self)
        self.thread_3.start(QtCore.QThread.HighestPriority)
        print(f'HighestPriority {self.thread_3.priority()}:')
        '''
        
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.update)
        self.timer.start(2000)

    def update(self):
        self.label_4.setText(f'{self.thread.sum:>20,}')
#        self.label_5.setText(f'{self.thread_2.sum:>20,}')
#        self.label_6.setText(f'{self.thread_3.sum:>20,}')
        self.label_time.setText(
            f'{str(int(self.label_time.text()) + 2):>26}'
        )
        if int(self.label_time.text()) == 102:
            self.timer.stop()


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    app.setFont(QtGui.QFont("Times", 12, QtGui.QFont.Bold))
    window = Window()
    window.resize(450, 152)
    window.show()
    sys.exit(app.exec_())

введите сюда описание изображения

  1. Пробуем запустить обе задачи указанные выше. Обратите внимание на загрузку ЦП - интерфейс практический лежит. Приоритеты работают как надо.

q1282746-QProcess.py

from PyQt5 import QtCore, QtGui, QtWidgets


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        
        self._process = QtCore.QProcess(self)
        self._process.start('python', ["q1282746-222.py"]) 

        self._process2 = QtCore.QProcess(self)
        self._process2.start('python', ["q1282746.py"]) 


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())

введите сюда описание изображения

  1. А теперь проделайте пункты 1, 2 и 3 предварительно раскомментировав строку self.msleep(1) - в q1282746.py и q1282746-222.py. Также обратите внимание на загрузку ЦП. Интерфейс работает нормально. Приоритеты не работают.

введите сюда описание изображения

→ Ссылка