写在前面

博主在学习Python编程过程中,有个问题一直没有理解透彻,就是多线程问题,因为工作中的项目都比较小,很少用到多线程,但是这个问题却是个很底层的问题,因此还是打算学习一下,查阅了一些资料,记录一下学习心得。

理解多线程

一般情况下,应用程序都是单线程运行的,但是对于GUI程序,可能一个线程无法满足要求,比如我有两个按钮A和B,我点击了一个按钮A,这个按钮的工作量很大,需要运行很长时间,然后我就把这个按钮的工作任务放到线程里面去,让它后台工作,这个时候,再点击另外一个按钮B,可以让这个按钮B开始工作。
先看看单线程的工作机制。

单线程执行两个按钮

在界面上设置按钮1和按钮2,按钮1打印数字1、2、3、4、5,按钮2打印a、b、c、d、e,我们大概率会这么写

from PyQt5.Qt import (QApplication, QWidget, QPushButton, QThread, QMutex, pyqtSignal)
import sys
import timeclass Demo(QWidget):def __init__(self):super().__init__()self.btn1 = QPushButton("按钮1", self)self.btn1.move(120, 80)self.btn1.clicked.connect(self.click1)self.btn2 = QPushButton("按钮2", self)self.btn2.move(120, 120)self.btn2.clicked.connect(self.click2)def click1(self):values = [1, 2, 3, 4, 5]for i in values:print(i)time.sleep(1)def click2(self):values = ["a", "b", "c", "d", "e"]for i in values:print(i)time.sleep(1)if __name__ == "__main__":app = QApplication(sys.argv)mywin = Demo()mywin.show()sys.exit(app.exec_())

看看运行情况

如果我点击按钮1后马上又点击按钮2,程序会出现假死的情况,必须得等按钮1的任务执行完才能开始按钮2的任务,这样也挺浪费资源的,所以这里考虑用多线程来解决这个问题。

多线程任务

现在考虑把这两个按钮的工作都放到线程里面去,来看看具体是怎么实施的,先上代码

# -*- coding: utf-8 -*-
"""
Created on Thu May 28 14:20:25 2020@author: HUANG Gang
"""
from PyQt5.Qt import (QApplication, QWidget, QPushButton, QThread, QMutex, pyqtSignal)
import sys
import timeclass Thread1(QThread):def __init__(self):super().__init__()def run(self):values = [1, 2, 3, 4, 5]for i in values:print(i)time.sleep(1)class Thread2(QThread):def __init__(self):super().__init__()def run(self):values = ["a", "b", "c", "d", "e"]for i in values:print(i)time.sleep(1)class Demo(QWidget):def __init__(self):super().__init__()self.btn1 = QPushButton("按钮1", self)self.btn1.move(120, 80)self.btn1.clicked.connect(self.click1)self.btn2 = QPushButton("按钮2", self)self.btn2.move(120, 120)self.btn2.clicked.connect(self.click2)def click1(self):self.thread1 = Thread1()self.thread1.start()def click2(self):self.thread2 = Thread2()self.thread2.start()if __name__ == "__main__":app = QApplication(sys.argv)mywin = Demo()mywin.show()sys.exit(app.exec_())

在创建应用程序之前,我把这两个按钮的工作任务写到两个独立的线程中去了,然后在界面程序里面实例化这两个线程,来看看执行情况

注意控制台的输出,在加入了这两个线程后,并未出现卡死的情况,线程之间不会相互干扰,但是有个问题,如果按钮1的线程任务完成之前重新点击了按钮1,那么这两个指令之间会产生干扰,就是按钮1的任务会刷新。这不是我希望发生的事情。
解决这个问题要用到线程锁。

线程锁

线程锁相对来说容易理解一点,就是在线程开始工作时,加上一把锁,在任务结束后,方可解锁,这样就可以保证整个任务是连续的,看代码

# -*- coding: utf-8 -*-
"""
Created on Thu May 28 14:20:25 2020@author: HUANG Gang
"""
from PyQt5.Qt import (QApplication, QWidget, QPushButton, QThread, QMutex, pyqtSignal)
import sys
import timeqmut1 = QMutex()
qmut2 = QMutex()class Thread1(QThread):def __init__(self):super().__init__()def run(self):qmut1.lock()  # 线程加锁values = [1, 2, 3, 4, 5]for i in values:print(i)time.sleep(1)qmut1.unlock()  # 线程解锁class Thread2(QThread):def __init__(self):super().__init__()def run(self):qmut2.lock()  # 线程加锁values = ["a", "b", "c", "d", "e"]for i in values:print(i)time.sleep(1)qmut2.unlock()  # 线程解锁class Demo(QWidget):def __init__(self):super().__init__()self.btn1 = QPushButton("按钮1", self)self.btn1.move(120, 80)self.btn1.clicked.connect(self.click1)self.btn2 = QPushButton("按钮2", self)self.btn2.move(120, 120)self.btn2.clicked.connect(self.click2)def click1(self):self.thread1 = Thread1()self.thread1.start()def click2(self):self.thread2 = Thread2()self.thread2.start()if __name__ == "__main__":app = QApplication(sys.argv)mywin = Demo()mywin.show()sys.exit(app.exec_())

在程序开始执行之前,先实例化两个线程锁,这两把锁分别加在两个线程之中,看看程序执行情况。

看看控制台的输出,1/2/3/4/5和a/b/c/d/e的输出是相对连续的,当然两个按钮之间还是会相互交叉打印,这也是多线程的精髓。
至此,我大概理解了多线程的使用方法,后面就可以进行更复杂的应用了。

多线程在PyQt5中的应用记录相关推荐

  1. 在多线程应用程序中使用循环缓冲区高效地进行日志记录

    在多线程应用程序中使用循环缓冲区高效地进行日志记录 在关键的计算机应用程序的生存期中,日志记录是一件非常重要的活动,特别是当故障的症状并不十分明显时.日志记录提供了故障前应用程序状态的详细信息,如变量 ...

  2. pyqt界面屏幕分辨率自适应_在Qt5和PyQt5中设置支持高分辨率屏幕自适应的方法

    在Qt5和PyQt5中设置支持高分辨率屏幕自适应的方法 PyQt5: 程序入口添加 QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHi ...

  3. python写一个数据库的界面_Python GUI教程(十四):在PyQt5中使用数据库

    在桌面图像化界面编程中,我们通常需要将一些数据或配置信息存储在本地.在本地进行数据的存储,我们可以直接使用文本文件,比如ini文件.csv文件.json文件等,或者是使用文件型的数据库(比如sqlit ...

  4. PyQt5中的QtDesinger界面各类属性

    PyQt5中 Qt Designer的使用 一.Designer各项介绍 1. 创建模板窗口 ​ 当我们点击配置好的External Tools中的QtDesigner时进入到Qt Designer的 ...

  5. java 清空一个list数据库_java – JPA EntityManager删除数据库中的所有记录

    我有一个插入我的数据库的Servlet.这工作正常.第二个Servlet显示第一个插入的内容,但每当我运行显示的Servlet时,我所有表中的所有记录都将被删除!我的JPA实现是 EclipseLin ...

  6. 【MySQL】面试官:如何查询和删除MySQL中重复的记录?

    写在前面 最近,有小伙伴出去面试,面试官问了这样的一个问题:如何查询和删除MySQL中重复的记录?相信对于这样一个问题,有不少小伙伴会一脸茫然.那么,我们如何来完美的回答这个问题呢?今天,我们就一起来 ...

  7. 利刃 MVVMLight 8:DispatchHelper在多线程和调度中的使用

    原文:利刃 MVVMLight 8:DispatchHelper在多线程和调度中的使用 在应用程序中,线程可以被看做是应用程序的一个较小的执行单位.每个应用程序都至少拥有一个线程,我们称为主线程,这是 ...

  8. python 动画场景_Python GUI教程(十五):在PyQt5中使用动画

    QT作为一个全面的桌面应用程序开发包,其自然提供了对图像的动画支持.本篇文章中,就来简单地在PYQt5中使用Animation动画功能. 本篇将会依次完成以下功能: 在GUI界面中显示一个图片(用一个 ...

  9. pyqt5 qscrollarea到达_在PYQT5中QscrollArea(滚动条)的使用方法

    如下所示: import sys from PyQt5.QtWidgets import * class MainWindow(QMainWindow): def __init__(self,): s ...

最新文章

  1. 还需要“attention”吗?一堆“前馈层”在ImageNet上表现得出奇得好
  2. 超越MobileNetV3,谷歌提出MobileDets:移动端目标检测新标杆
  3. P3694-邦邦的大合唱站队【状压dp】
  4. [包计划] node-fs-extra
  5. 远程连接电脑_Python黑科技:在家远程遥控公司电脑,python+微信一键连接!
  6. 面试题之Java内存区域
  7. 计算机显示技术发展,显示技术
  8. C++---------之--------【虚析构函数】
  9. Jquery动态进行图片缩略
  10. 三农数据(1996-2020)九:产值:谷物及其他作物、蔬菜园艺、水果、坚果、饮料
  11. itest听力答案2020_itest答案
  12. 机器学习:AI数据集划分(训练集、验证集、测试集)
  13. 安卓android百度图像识别 摄像头黑屏问题
  14. 混合动力simulink模型 转卖新能源混动车型模式转换说明,包含HCU模式转换simulink框图及说明文档
  15. 不重装系统改硬盘模式: RAID ON 改成 AHCI
  16. 为什么从此电脑访问不了ftp_蓝奏云网盘为什么访问不了?(附资源)
  17. 独孤思维:什么项目又好又赚钱?
  18. 2022安全员-C证考试题库模拟考试平台操作
  19. 人工智能入门算法逻辑回归学习笔记
  20. html表格框线怎么弄实心的,HTML5绘制实心的文本

热门文章

  1. MySQL 查询距离指定日期最近的数据
  2. 从零开始学linux
  3. 品牌营销的反思录:品牌、市场与营销学习心得笔记
  4. 倒计时抢(数据分析)
  5. 硬盘主要参数详解(上)
  6. iview 表单验证问题 Select 已经选择 还是弹验证提示
  7. 如何将Markdown文章轻松地搬运到微信公众号并完美地呈现代码内容
  8. [转贴]一个26岁IT男人写在辞职后
  9. 关于充分必要条件的充分性和必要性
  10. 啦啦外卖60.1最新版本全开源独立版本源码小程序+app+h5全端