• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

详解python中的线程与线程池

python 搞代码 4年前 (2022-01-08) 20次浏览 已收录 0个评论

这篇文章主要介绍了python线程与线程池,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

线程

进程和线程

什么是进程?

进程就是正在运行的程序, 一个任务就是一个进程, 进程的主要工作是管理资源, 而不是实现功能

什么是线程?

线程的主要工作是去实现功能, 比如执行计算.

线程和进程的关系就像员工与老板的关系,

老板(进程) 提供资源 和 工作空间,

员工(线程) 负责去完成相应的任务

特点

一个进程至少由一个线程, 这一个必须存在的线程被称为主线程, 同时一个进程也可以有多个线程, 即多线程

当我们我们遇到一些需要重复执行的代码时, 就可以使用多线程分担一些任务, 进而加快运行速度

线程的实现

线程模块

Python通过两个标准库_thread和threading, 提供对线程的支持 , threading对_thread进行了封装。
threading模块中提供了Thread , Lock , RLock , Condition等组件。

因此在实际的使用中我们一般都是使用threading来实现多线程

线程包括子线程和主线程:

主线程 : 当一个程序启动时 , 就有一个线程开始运行 , 该线程通常叫做程序的主线程

子线程 : 因为程序是开始时就执行的 , 如果你需要再创建线程 , 那么创建的线程就是这个主线程的子线程

主线程的重要性体现在两方面 :

  1. 是产生其他子线程的线程
  2. 通常它必须最后完成执行, 比如执行各种关闭操作

Thread类

常用参数说明

参数 说明
target 表示调用的对象, 即子线程要执行的任务, 可以是某个内置方法, 或是你自己写的函数
name 子线程的名称
args 传入target函数中的位置参数, 是一个元组, 参数后必须加逗号

常用实例方法

方法 作用
Thread.run(self) 线程启动时运行的方法, 由该方法调用 target参数所指定的函数
Thread.start(self) 启动进程, start方法就是区帮你调用run方法
Thread.terminate(self) 强制终止线程
Thread.join(self, timeout=None) 阻塞调用, 主线程进行等待
Thread.setDaemon(self, daemonic) 将子线程设置为守护线程, 随主线程结束而结束
Thread.getName(self, name) 获取线程名
Thread.setName(self, name) 设置线程名

创建线程

在python中创建线程有两种方式, 实例Thread类和继承重写Thread类

实例Thread类

 import threading import time def run(name, s): # 线程要执行的任务 time.sleep(s) # 停两秒 print('I am %s' % name) # 实例化线程类, 并传入函数及其参数, t1 = threading.Thread(target=run, name='one', args=('One', 5)) t2 = threading.Thread(target=run, name='two', args=('Two', 2)) # 开始执行, 这两个线程会同步执行 t1.start() t2.start() print(t1.getName())		# 获取线程名 print(t2.getName()) # Result: one two I am Two	# 运行2s后 I am One	# 运行5s后 

继承Thread类

 class MyThread(threading.Thread): # 继承threading中的Thread类 # 线程所需的参数 def __init__(self, name, second): super().__init__() self.name = name self.second = second # 重写run方法,表示线程所执行的任务,必须有 def run(self): time.sleep(self.second) print('I am %s' % self.name) # 创建线程实例 t1 = MyThread('One', 5) t2 = MyThread('Two', 2) # 启动线程,实际上是调用了类中的run方法 t1.start() t2.start() t1.join() print(t1.getName()) print(t2.getName()) # Result: I am Two	# 运行后2s I am One	# 运行后5s One Two 

常用方法

join()

阻塞调用程序 , 直到调用join () 方法的线程执行结束, 才会继续往下执行

<a style="color:transparent">来源gao($daima.com搞@代@#码(网</a> # 开始执行, 这两个线程会同步执行 t1.start() t2.start() t1.join()	# 等待t1线程执行完毕,再继续执行剩余的代码 print(t1.getName()) print(t2.getName()) # Result: I am Two I am One one two 

setDemon()

使用给线程设置守护模式: 子线程跟随主线程的结束而结束, 不管这个子线程任务是否完成. 而非守护模式的子线程只有在执行完成后, 主线程才会执行完成

setDaemon() 与 join() 基本上是相对的 , join会等子线程执行完毕 ; 而setDaemon则不会等

 def run(name, s): # 线程要执行的函数 time.sleep(s) # 停两秒 print('I am %s' % name) # 实例化线程类, 并传入函数及其参数 t1 = threading.Thread(target=run, name='one', args=('One', 5)) t2 = threading.Thread(target=run, name='two', args=('Two', 2)) # 给t1设置守护模式, 使其随着主线程的结束而结束 t1.setDaemon(True) # 开始执行, 这两个线程会同步执行 t1.start() t2.start()	# 主线程会等待未设置守护模式的线程t2执行完成 # Result: I am Two	# 运行后2s 

线程间的通信

互斥锁

在同一个进程的多线程中 , 其中的变量对于所有线程来说都是共享的 , 因此 , 如果多个线程之间同时修改一个变量 , 那就乱套了 , 共享的数据就会有很大的风险 , 所以我们需要互斥锁 , 来锁住数据 , 防止篡改。

来看一个错误的示范:

 a = 0 def incr(n): global a for i in range(n): a += 1 # 这两个方法同时声明了变量a,并对其进行修改 def decr(n): global a for i in range(n): a -= 1 t_incr = threading.Thread(target=incr, args=(1000000,)) t_decr = threading.Thread(target=decr, args=(1000000,)) t_incr.start() t_decr.start() t_incr.join() t_decr.join() print(a) # 期望结果应该是0, 但是因为这里没有设置互斥锁, 所以两个方法是同时对同一个变量进行修改, 得到的的结果值是随机的 

下面我们改一下上面的代码 , 两个方法加上互斥锁:

 a = 0 lock = threading.Lock()	# 实例化互斥锁对象, 方便之后的调用 def incr(n): global a for i in range(n): lock.acquire()	# 上锁的方法 a += 1 lock.release()	# 解锁的方法 # 要注意的是上锁的位置是, 出现修改操作的代码 def decr(n): global a for i in range(n): with lock:	# 也可以直接使用with, 自动解锁 a -= 1 t_incr = threading.Thread(target=incr, args=(1000000,))

以上就是详解python中的线程与线程池的详细内容,更多请关注gaodaima搞代码网其它相关文章!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:详解python中的线程与线程池

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址