Python多线程笔记(Python_MultiThread)

2023-05-16

4.MultiThreading(多线程)使用:

a. 什么是多线程?

简单明了,让计算机在同一时间内同时运行多个程序,并且每个程序的计算互不干扰,我们称这样的操作为多线程运算。

b. add thread(添加线程)

首先,我们要在代码中导入线程模块也就是import threading。介绍几个常用的方法

import threading
'''
1.threading.active_count():计算当前激活的线程个数,也就是说,当前程序有几个线程在运行。
2.threading.enumerate():返回一个当前激活的线程名称Name的列表
3.threading.current_thread():当前运行的线程的名称Name
'''
def main():
  print(threading.active_count())
  print(threading.enumerate())
  print(threading.current_thread())
if __name__ == '__main__':
  main()
# result:根据每个人的计算机不同,打印出来的个数,名称也不一样

'''
Add Thread:
添加一个线程:变量名 = threading.Thread(target = 操作方法名, name = "别名"),参数中的操作方法名是指你定义给这个线程需要做的事情,比如打印某个东西,计算某个东西,写成一个方法,在传入该方法名即可,name参数是给线程起一个方便我们观察的别名。如下:
'''
def thread_job_1():
  print("This is an added Thread, Name is %s" % (threading.current_thread()))
def main():
  added_thread1 = threading.Thread(target = thread_job_1, name = "Thread1")
  #print(threading.active_count())
  #print(threading.enumerate())
  #print(threading.current_thread())
  added_thread1.start() # 一定要启动刚刚添加的线程,不然线程不会自动进行工作.当代码运行后,至少会有一个main线程去执行
if __name__ == '__main__':
  main()

b. threading中join的功能:

Join(): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。先来看一个例子:

import threading
import time
def thread_job_1():
  print("Thread1 start")
  for i in range(10):
    time.sleep(0.5)  #time.sleep(t)让程序睡眠t秒
  print("Thread1 end")
def main():
  added_thread1 = threading.Thread(target = thread_job_1)
  added_thread1.start() # 一定要启动刚刚添加的线程,不然线程不会自动进行工作.当代码运行后,至少会有一个main线程去执行
  print("All finish")
if __name__ == '__main__':
  main()
  
  '''
  result:
  Thread1 start
	All finish
	Thread1 end
	可以看出来主线程没有等待Thread1运行完就开始执行了,而join函数可以很好避免这种情况的发生。
  '''
def thread_job_1():
  print("Thread1 start")
  for i in range(10):
    time.sleep(0.5)  #time.sleep(t)让程序睡眠t秒
  print("Thread1 end")
def main():
  added_thread1 = threading.Thread(target = thread_job_1)
  added_thread1.start() # 一定要启动刚刚添加的线程,不然线程不会自动进行工作.当代码运行后,至少会有一个main线程去执行
  added_thread1.join() #在这里加入join函数就可以让主线程等待子线程1执行完再继续执行了
  print("All finish")
if __name__ == '__main__':
  main()

c. Threading中的Queue

Python 的 Queue 模块中提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列 PriorityQueue。

这些队列都实现了锁原语,能够在多线程中直接使用,可以使用队列来实现线程间的同步。

Queue 模块中的常用方法:

  • Queue.qsize() 返回队列的大小
  • Queue.empty() 如果队列为空,返回True,反之False
  • Queue.full() 如果队列满了,返回True,反之False
  • Queue.full 与 maxsize 大小对应
  • Queue.get([block[, timeout]])获取队列,timeout等待时间
  • Queue.get_nowait() 相当Queue.get(False)
  • Queue.put(item) 写入队列,timeout等待时间
  • Queue.put_nowait(item) 相当Queue.put(item, False)
  • Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
  • Queue.join() 实际上意味着等到队列为空,再执行别的操作

由于Threading中的工作是不能返回值的,所以线程之间的通信依靠Queue来完成,如下:

import threading
import time
from queue import Queue
def thread_work(l, q):
    for i in range(len(l)):
        l[i] = l[i] ** 2
    q.put(l)

def multithreading_work():
    q = Queue()
    threads = []
    data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    for i in range(3):
        t = threading.Thread(target= thread_work, args=(data[i], q)) # 创建线程中方法使用args添加参数
        t.start()
        threads.append(t)
    for thread in threads: # 控制每个线程依次执行
        thread.join()
    results = []
    for i in range(3):
        results.append(q.get())
    print(results)
if __name__ == '__main__':
    multithreading_work()

d. Python中的GIL机制

由于Python中拥有GIL(Global Interpreter Lock)全局解释器锁的存在。会导致多线程状况下也不能够很大程序的将多个任务执行的效率提高。所以我们要使用multiprocessing(多进程)来加快不同任务的计算。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UWgOf9jp-1594565574835)(/Users/liyan/Library/Application Support/typora-user-images/image-20200709154232785.png)]

下面举一个例子,让一个线程循环执行多个操作。让多个线程分别执行多个操作。比较二者的速度

import threading
from queue import Queue
import copy
import time

def job(l, q):
    res = sum(l)
    q.put(res)

def multithreading(l):
    q = Queue()
    threads = []
    for i in range(4):
        t = threading.Thread(target=job, args=(copy.copy(l), q), name='T%i' % i)
        t.start()
        threads.append(t)
    [t.join() for t in threads]
    total = 0
    for _ in range(4):
        total += q.get()
    print(total)

def normal(l):
    total = sum(l)
    print(total)

if __name__ == '__main__':
    l = list(range(1000000))
    s_t = time.time()
    normal(l*4)
    print('normal: ',time.time()-s_t)
    s_t = time.time()
    multithreading(l)
    print('multithreading: ', time.time()-s_t)
#result :normal:  0.06258893013000488      multithreading:  0.05690884590148926
#可以发现多线程处理并没有比单线程快多少时间

e.Python中的Lock锁机制(线程同步)

如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。

使用 Thread 对象的 Lock 和 Rlock 可以实现简单的线程同步,这两个对象都有 acquire 方法和 release 方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到 acquire 和 release 方法之间。如下:

多线程的优势在于可以同时运行多个任务(至少感觉起来是这样)。但是当线程需要共享数据时,可能存在数据不同步的问题。

考虑这样一种情况:一个列表里所有元素都是0,线程"set"从后向前把所有元素改成1,而线程"print"负责从前往后读取列表并打印。

那么,可能线程"set"开始改的时候,线程"print"便来打印列表了,输出就成了一半0一半1,这就是数据的不同步。为了避免这种情况,引入了锁的概念。

锁有两种状态——锁定和未锁定。每当一个线程比如"set"要访问共享数据时,必须先获得锁定;如果已经有别的线程比如"print"获得锁定了,那么就让线程"set"暂停,也就是同步阻塞;等到线程"print"访问完毕,释放锁以后,再让线程"set"继续。

经过这样的处理,打印列表时要么全部输出0,要么全部输出1,不会再出现一半0一半1的尴尬场面。

参考例子:

import threading

def job1():
    global A, lock
    lock.acquire()
    for i in range(10):
        A += 1
        print('job1', A)
    lock.release()

def job2():
    global A, lock
    lock.acquire()
    for i in range(10):
        A += 10
        print('job2', A)
    lock.release()

if __name__ == '__main__':
    lock = threading.Lock()
    A = 0
    t1 = threading.Thread(target=job1)
    t2 = threading.Thread(target=job2)
    t1.start()
    t2.start()
    t1.join()
    t2.join()

代码地址:Code欢迎给个star

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python多线程笔记(Python_MultiThread) 的相关文章

随机推荐

  • 复杂网络建模的实现(哈工大深圳复杂网络建模课程Project)

    任务 xff1a 1 xff0c 三张不同的网络 xff1a 已知某人的名称 已知某人的家乡 已知某人的方言 分析这三者各自的网络性能 xff08 节点度数分布 平均最短路径长度 集聚系数 xff09 以及动态行为 xff08 在刻意攻击
  • 免登陆Oracle官网下载JDK

    Oracle官网下载JDK 方法一 免登录下载 进入官网 xff0c 选择需要下载的JDK版本 xff0c 这里以JDK8为例 点击下载 xff0c 勾选同意 在正常情况下 xff0c 点击 Download jdk 8u333 windo
  • linux rancher 清理docker容器磁盘空间

    目录说明 var lib docker containers xff1a 是 Docker 在 Linux 系统上默认存储容器信息的目录 在该目录下 xff0c 每个运行的 Docker 容器都有一个单独的目录 xff0c 以容器 ID 命
  • 如何在官网下载COCO数据集

    官网地址 xff1a https cocodataset org download 1 选择下载的数据 xff0c 右键 xff0c 获取下载地址 2 将 http 改为 https 示例获得的下载地址为 xff1a http images
  • 两个互相引用对象的垃圾回收

    部分转自 xff1a 深入理解java虚拟机 一书 判断对象是否存活 1 引用计数算法 给对象添加一个引用计数器 xff0c 每当有一个地方引用它时 xff0c 计数器值就加1 当引用失效时 xff0c 计数器值就减1 任何时刻计数器为0的
  • ssm整合时,通过jdbc.properties文件无法连接mysql问题

    最近在重温ssm框架 在搭建基础的项目进行单元测试时 xff0c 发现无法连接mysql数据库 通过各种查资料终于发现了原因 原始jdbc properties文件 由于username这个属性会被系统的username变量覆盖 xff0c
  • Mysql数据库之左连接left join 右连接right join 内连接inner join

    最近 xff0c 公司的用户达到了700 43 万 xff0c 意味着数据库已经达到700 43 万 xff0c 聊聊傻傻分不清的连接查询吧 xff01 前提 数据库中一共有三个表 class book phone 而且每个数据库表中都有1
  • VMware虚拟机软件,配置Linux Ubuntu操作系统环境,及安装问题总结大全

    文章目录 1 xff1a 前言2 xff1a 基本认识3 下载环境4 xff1a VM虚拟机的安装5 xff1a ubuntu的下载6 xff1a 把ubuntu安装在VM虚拟机上7 VMware Tools工具8 Source insig
  • linux常用命令(Beginner note)

    命令 ls 列出所有文件及文件夹 ls 路径 xff1a 列出所给路径下的所有文件及文件夹 选项 xff1a xff08 可组合使用 xff0c 也可简写组合形式 xff0c 例 xff1a alh xff0c 无先后顺序 xff09 a
  • 利用JS-SDK微信分享接口调用(后端.NET)

    一直都想研究一下JS SDK微信分享的接口调用 xff0c 由于最近工作需要 xff0c 研究了一下 xff0c 目前只是实现了部分接口的调用 xff1b 其他接口调用也是类似的 xff1b 在开发之前 xff0c 需要提前准备一个微信公众
  • Linux文件查找find

    1 find查找概述 为什么要有文件查找 xff0c 因为很多时候我们可能会忘了某个文件所在的位置 xff0c 此时就需要通过find来查找 find命令可以根据不同的条件来进行查找文件 xff0c 例如 xff1a 文件名称 文件大小 文
  • Linux文件打包与压缩

    1 文件打包与压缩 1 什么是文件压缩 将多个文件或目录合并成为一个特殊的文件 比如 搬家 脑补画面 img 2 为什么要对文件进行压缩 xff1f 当我们在传输大量的文件时 xff0c 通常都会选择将该文件进行压缩 xff0c 然后在进行
  • 集中式版本管理SVN与分布式版本管理Git的区别

    集中式版本控制系统SVN CVS 先说集中式版本控制系统 xff0c 版本库是集中存放在中央服务器的 xff0c 而大家工作的时候 xff0c 用的都是自己的电脑 xff0c 所以要先从中央服务器取得最新的版本 xff0c 然后开始工作 x
  • chatgpt Linux 定时任务 清理rancher pod启动服务的日志文件 脚本

    Linux 定时任务执行命令 假设我们想要每隔X分钟 每隔X天 每天X点执行一个脚本文件 xff0c 可以使用 Linux 自带的 cron 工具来创建定时任务 清理步骤 您可以使用 Linux 自带的 cron 工具来创建定时任务 xff
  • Http协议的几种常见状态码

    在开发好了网站后 xff0c 用户通过URL对资源进行操作 xff0c 服务器端要告诉用户交互的结果 xff0c 比如新增资源是成功还是失败了 一个较好的办法就是遵循HTTP协议 xff0c 使用请求响应的HTTP状态码 xff08 Sta
  • 推荐画UML图以及流程图的在线网站Site

    记得当年学UML课程的时候 xff0c 当你还在为了安装Rose而发愁的时候 xff0c 人家都把作业给交了 xff0c 并且现在大多数UML课程都会让学生使用Rational Rose做画图练习 近来 xff0c 做毕业设计需要提供各种流
  • 浙大PTA平台上的题目题解

    记载一些题目的代码 xff0c 之后想要在b站讲题目 xff0c 到时候会把录的视频上传b站 不是大佬 xff0c 是蒟蒻 xff0c 大佬勿喷 xff0c 仅供参考 xff0c 欢迎大家star xff0c qwq 浙大版 C语言程序设计
  • git 入门教程

    想要将一个项目托管到github xff0c 需要进入项目所在文件夹进行git init命令初始化 Git提交代码的基本流程 xff1a 创建或修改 本地文件使用 git add 命令 xff0c 将创建或修改的文件添加到本地的暂存区 xf
  • 博客搬家

    谢谢大家对我的blog的支持 现在本科毕业 xff0c 准备读研 方向大概是机器学习这一块 又是一个新的开始 我想将我读研学习Python以及机器学习 深度学习 以及数据分析处理 大数据等学习教程放在新的blog上 xff1a blog 欢
  • Python多线程笔记(Python_MultiThread)

    4 MultiThreading 多线程 使用 xff1a a 什么是多线程 xff1f 简单明了 xff0c 让计算机在同一时间内同时运行多个程序 xff0c 并且每个程序的计算互不干扰 xff0c 我们称这样的操作为多线程运算 b ad