Python 多线程、守护进程、同时运行最大线程数、锁、线程阻塞(线程暂停和继续)
python 多线程的使用笔记
1、多线程的基本用法
(1)简单任务多线程的开启方式
from threading import Thread
import timedef target(name, n):for i in range(0, n, 2):print(f'{name}_{i}')time.sleep(1)t1 = Thread(target=target, args=('a', 16, ))
t1.start()for i in range(1, 11, 2):print(f'主线程_{i}')time.sleep(1)
(2)自定义复杂任务多线程的开启方式,适合复杂逻辑
from threading import Thread
import timeclass myThread(Thread):def __init__(self, name, n):super(myThread, self).__init__()self.name = nameself.n = ndef run(self):for i in range(0, self.n, 2):print(f'{self.name}_{i}')time.sleep(1)t1 = myThread('a', 16, )
t1.start()for i in range(1, 11, 2):print(f'主线程_{i}')time.sleep(1)
2、关于守护线程和 join
正常情况下主线程和子线程可以相互没有干扰,独立运行完后程序结束
当我们需要主线程结束后子线程也随着结束,可以将子线程设置为守护线程后,这样主线程结束后,即便子线程没有运行完,子线程也会随着主线程结束
这里注意的是,子线程设置守护线程一定要在子线程开始之前
当我们需要子线程运行完主线程再接着往下运行时,子线程可以调用 join()
方法, 主线程就会等待,直到子线程终止或者超时才会继续往下执行
这里注意的是,子线程 join()
一定要在子线程开始之后
jion()
里面可以传入 timeout
参数,超时后主线程会继续往下运行
下面是 setDaemo()
和 join()
的例子 可以去掉注释看看有什么不同
from threading import Thread
import timedef target(name, n):for i in range(0, n, 2):print(f'{name}_{i}')time.sleep(1)t1 = Thread(target=target, args=('a', 16,))
# t1.setDaemon(True)
t1.start()
# t1.join()for i in range(1, 11, 2):print(f'主线程_{i}')time.sleep(1)
3、关于信号量 Semaphore()
和 BoundedSemaphore()
我们可以一次开启很多线程,但是我们想对同时运行的线程控制在一定数量内,开启的线程大于同时运行的线程时,其他的线程就处于阻塞状态,直到有线程运行结束,阻塞的线程才能开始运行,这时我们就用到 Semaphore()
,
信号量基于内部计数器,初始化 Semaphore()
时会给计数器一个值,每调用一次acquire()
,计数器减1,每调用一次release()
, 计数器加1,当计数器为0时,acquire()
调用被阻塞
from threading import Thread, Semaphore
import timesema = Semaphore(3)def target(name, n):sema.acquire()for i in range(0, n, 2):print(f'{name}_{i}')time.sleep(1)sema.release()sema = Semaphore(3)for s in 'abcde':Thread(target=target, args=(s, 6,)).start()
Semaphore()
支持上下文,对于上面代码,也可以这样写
from threading import Thread, Semaphore
import timesema = Semaphore(3)def target(name, n):with sema:for i in range(0, n, 2):print(f'{name}_{i}')time.sleep(1)sema = Semaphore(3)for s in 'abcde':Thread(target=target, args=(s, 6,)).start()
BoundedSemaphore
继承自 Semaphore
功能和 Semaphore
基本一样,只不过 BoundedSemaphore
有限制,release()
时会判断当前信号量的值,如果当前值大于等于初始值,就会抛出错误,而Semaphore
并不会抛出异常
4 锁 Lock
和 RLock
如果运行上面代码,我们会发现,多个子线程之间可能打印在一行上,比较混乱,这是由于线程之间随机调度,同时输出。如果是同时在修改一个变量。或者一个文件,就有可能造成数据错误,这时互斥锁Lock
就派上用场了。Lock
可以用于锁定资源,Lock
有两个基本方法,acquire()
和 release()
,调用acquire()
状态变为锁定并立即返回,当状态是锁定时, acquire()
将阻塞至其他线程调用 release()
将其改为非锁定状态,然后 acquire()
调用重置其为锁定状态并返回。锁支持上下文管理协议,即支持with语
句
from threading import Thread, Lock
import timelock = Lock()def target(name, n):for i in range(0, n, 2):lock.acquire()print(f'{name}_{i}')lock.release()time.sleep(1)for s in 'abcde':Thread(target=target, args=(s, 6,)).start()
用with
语句代替
from threading import Thread, Lock
import timelock = Lock()def target(name, n):for i in range(0, n, 2):with lock:print(f'{name}_{i}')time.sleep(1)for s in 'abcde':Thread(target=target, args=(s, 6,)).start()
如果尝试释放一个非锁定的锁,则会引发 RuntimeError
异常
RLock
被称为重入锁,若要锁定锁,线程调用其 acquire()
方法;一旦线程拥有了锁,方法将返回。若要解锁,线程调用 release()
方法。 acquire()/release()
对可以嵌套,重入锁必须由获取它的线程释放。一旦线程获得了重入锁,同一个线程再次获取它将不阻塞。只有最终release()
(最外面一对的 release()
) 将锁解开,才能让其他线程继续处理 acquire()
阻塞,线程必须在每次获取它时释放一次。
Lock
和 RLock
用法大体相同,区别在于Lock
在锁定时不属于特定线程,也就是说,Lock
可以在一个线程中上锁,在另一个线程中解锁。而对于RLock
来说,只有当前线程才能释放本线程上的锁,即解铃还须系铃人。
5 Event
事件
Event
内部定义了一个标志位flag
,初始的时候为False
,当Flag
的值为False
,那么event.wait()
就会阻塞,当flag
值为True
,那么event.wait()
便不再阻塞Event
主要提供以下方法
set()
来将其设置为True
;
clear()
将其重新设置为False
;
is_set()
来检查标志位的状态;
wait(timeout=None)
,会一直监听flag
,如果flag
为False
就一直处于阻塞状态
from threading import Thread, Event
import timeclass myThread(Thread):def __init__(self, name, n):super(myThread, self).__init__()self.name = nameself.n = nself.e = Event()def pause(self): # 暂停self.e.clear()def play(self): # 继续self.e.set()def run(self):for i in range(0, self.n, 2):self.e.wait()print(f'{self.name}_{i}')time.sleep(1)t1 = myThread('a', 16, )
t1.play()
t1.start()for i in range(1, 11, 2):print(f'主线程_{i}')time.sleep(1)if i == 3:t1.pause() # 子线程暂停if i == 7:t1.play() # 子线程继续
特别感谢下面两篇文章的作者,供大家做参考学习
python多线程详解(超详细)
python threading模块的Lock和RLock区别
Python 多线程、守护进程、同时运行最大线程数、锁、线程阻塞(线程暂停和继续)相关推荐
- python多线程守护线程_Python守护程序线程
python多线程守护线程 In this tutorial we will be learning about Python Daemon Thread. In our previous tutor ...
- python实现守护进程_守护进程原理及Python实现
守护进程原理及Python实现 守护进程,不依赖于终端,在后台运行的程序,通常称为daemon(ˈdiːmən或ˈdeɪmən). 一些常见的Linux软件通常都是已守护进程的方式运行,比如: ngi ...
- 守护进程与后台进程(Python 创建守护进程)
文章目录 一.守护进程与后台进程 1. 守护进程 1.1 代码实现 为什么要fork两次 umask权限掩码 进程组 会话组 2. 后台进程 3. 守护进程与后台进程区别 4. 使用场景总结 二.参考 ...
- python统计csv行数_对Python 多线程统计所有csv文件的行数方法详解
如下所示: #统计某文件夹下的所有csv文件的行数(多线程) import threading import csv import os class MyThreadLine(threading.Th ...
- 一文详解java线程池 详解Java线程池的七个参数 详解池化技术 java如何选择核心线程数 详解Java线程池的拒绝策略
目录 引言 线程池使用场景 加快请求响应(响应时间优先) 加快处理大任务(吞吐量优先) 特殊说明 线程池的池化技术 线程池的创建 手动创建 创建newFixedThreadPool线程池 创建newS ...
- Linux最大线程数限制及当前线程数查询
Linux最大线程数限制及当前线程数查询 1.总结系统限制有: /proc/sys/kernel/pid_max #查系统支持的最大线程数,一般会很大,相当于理论值 /proc/sys/kernel/ ...
- Day9 - Python 多线程、进程 --转自金角大王
本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者 ...
- 怎样利用Python制作守护进程
有时候我们的需要制作一些守护进程,如果服务器出现了什么问题,就需要重启某个软件啊之类的 那么这类守护进程怎么做呢? 请看代码 import time seconds_to_sleep = 2 * 60 ...
- python实现守护进程_Python如何实现守护进程的方法示例
Python如何实现守护进程的方法示例 来源:中文源码网 浏览: 次 日期:2018年9月2日 [下载文档: Python如何实现守护进程的方法示例.txt ] (友情提示:右键点上行t ...
- python fork 守护进程
# -*-coding:utf-8-*- import sys, os'''将当前进程fork为一个守护进程注意:如果你的守护进程是由inetd启动的,不要这样做!inetd完成了所有需要做的事情,包 ...
最新文章
- vlfeat 特征检测
- java 获取活动窗口_用Java获取活动窗口信息
- 杜克大学出来的NBA球星有哪些?
- mint-ui 中 Infinite scroll 在tab-container中使用数据全部加载的问题
- 如何打开Tango的ADF文件?
- SpringBoot 自带工具类~断言
- C语言 · 龟兔赛跑预测
- 教授先生带你学习链表:链表节点的删除与增添2
- Linux下,Pycharm到期,源不好使,无法安装pyqt5及pyqy5-tools的解决办法
- php nsdata,转换NSArray- JSON- NSData- PHP服务器- JSON表示
- 【教程搬运】廖雪峰Git的使用教程(一)
- 使用Windows批处理文件递归删除当前路径下的指定文件夹
- 2022年来啦!丨新年回馈粉丝丨免费抽奖!
- Web防火墙(WAF)是什么?和传统防火墙区别是什么?
- 详细前端面试题javascript篇--持续更新
- mybatis lazyload
- vue组件间通信六种方式
- Spring Boot与Elasticsearch的对应版本
- 高考投档计算机检索,高考志愿投档
- 第0章 计算机硬件与组成基础