python学习笔记(九)——线程与进程
一、线程
Python 中为我们提供了两个模块来创建线程。
- _thread
- threading
thread 模块已被废弃。用户可以使用 threading 模块代替。所以,在 Python 中不能再使用"thread" 模块。为了兼容性,Python 将 thread 重命名为 “_thread”。
相对 _thread 模块来说, threading 模块更加高级也更加常用。
多线程
创建多线程步骤:
- 导入线程库
- 创建任务函数
- 创建线程对象
- 启动线程
实例:
import threading,time
def task():
for i in range(1,11):
time.sleep(1)
print(threading.current_thread().name,end="")
print(":output >%d"%i)
print(time.ctime())
# 创建两个线程
pt1=threading.Thread( target=task )
pt2=threading.Thread( target=task )
# 输出线程名
print(threading.current_thread().name)
# 启动线程
pt1.start()
pt2.start()
pt1.join()
pt2.join()
print(time.ctime())
输出:
Sat Mar 14 16:07:12 2020
MainThread
Thread-2:output >1
Thread-1:output >1
Thread-1Thread-2:output >2
:output >2
Thread-1Thread-2:output >3
:output >3
Thread-1Thread-2:output >4
:output >4
Thread-1:output >5
Thread-2:output >5
Thread-1Thread-2:output >6
:output >6
Thread-2:output >7
Thread-1:output >7
Thread-2Thread-1:output >8
:output >8
Thread-2:output >9
Thread-1:output >9
Thread-1:output >10
Thread-2:output >10
Sat Mar 14 16:07:22 2020
可以看到一共用了10秒时间,两个线程都完成了自己的任务。
使用 threading.Thread( ) 创建线程时,可以传入六个参数,比如线程名 name,任务函数参数 args等。
def __init__(self, group=None, target=None, name=None,
args=(), kwargs=None, *, daemon=None):
其中,如name、daemon等参数除了在创建线程时指定以外,还可以通过对象调用函数设置。 pt.setName()、pt.setDaemon()。
线程同步
在多线程中会常会发生多个线程同时访问同一个资源的情况,造成线程不安全。而我们要求线程对临界资源的操作是必须是原子操作,因此我们可以通过线程锁来实现线程安全。
使用 Thread 对象的 Lock 和 Rlock 可以实现简单的线程同步,这两个对象都有 acquire 方法和 release 方法进行加锁和解锁。
lock=threading.RLock() # 创建一个锁
lock.acquire() # 加锁
lock.release() # 解锁
把每次只允许一个线程操作的数据,放到 acquire 和 release 方法之间进行操作。
全局解释器锁GIL
在非python环境中,单核情况下,同时只能有一一个任务执行。多核时可以支持多个线程同时执行。但是在python中,无论有多少核,同时只能执行一个线程。究其原因,这就是由于GIL的存在导致的。
GIL的全称是Global Interpreter Lock(全局解释器锁),来源是python设计之初的考虑,为了数据安全所做的决定。某个线程想要执行,必须先拿到GIL,我们可以把GIL看作是“通行证”,并且在一个python进程中,GIL只有一 一个。拿不到通行证的线程,就不允许进入CPU执行。GIL 只在cpython中才有,因为cpython调用的是c语言的原生线程,所以他不能直接操作cpu,只能利用GIL保证同一-时间只能有- -个线程拿到数据。而在pypy和ipython中是没有GIL的。
所以,在Python中,可以使用多线程,但不要指望能有效利用多核。不过,也不用过于担心,Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务。多个Python进程有各自独立的GIL锁,互不影响
二、进程
使用多进程同样可以完成多线程的工作,我们将之前的多线程程序改成多进程程序。
import multiprocessing
import time
def task():
for i in range(1,11):
time.sleep(1)
print(multiprocessing.current_process().name,__name__,end="")
print(":output >%d"%i)
if __name__=="__main__":
print(time.ctime())
p1=multiprocessing.Process(target=task)
p2=multiprocessing.Process(target=task)
p1.start()
p2.start()
p1.join()
p2.join()
print(time.ctime())
输出:
Sat Mar 14 17:25:31 2020
Process-1 __mp_main__:output >1
Process-2 __mp_main__:output >1
Process-1 __mp_main__:output >2
Process-2 __mp_main__:output >2
Process-1 __mp_main__:output >3
Process-2 __mp_main__:output >3
Process-1 __mp_main__:output >4
Process-2 __mp_main__:output >4
Process-1 __mp_main__:output >5
Process-2 __mp_main__:output >5
Process-1 __mp_main__:output >6
Process-2 __mp_main__:output >6
Process-1 __mp_main__:output >7
Process-2 __mp_main__:output >7
Process-1 __mp_main__:output >8
Process-2 __mp_main__:output >8
Process-1 __mp_main__:output >9
Process-2 __mp_main__:output >9
Process-1 __mp_main__:output >10
Process-2 __mp_main__:output >10
Sat Mar 14 17:25:41 2020
进程池
通过进程池 pool 可以批量的创建大量的进程。
import multiprocessing
import os
import time
def task(i):
print("线程%d 执行: pid=%s"%(i,os.getpid()))
time.sleep(1)
return i
def back(n):
print("任务%d已完成"%n)
if __name__=="__main__":
mypool=multiprocessing.Pool(5) # 线程池大小
for i in range(1,21): # 20个线程任务
mypool.apply_async(func=task,args=(i,))
mypool.close()
mypool.join()
apply_async() 会等待线程池中有空闲时依次执行线程任务。其中,callback 参数是回调函数。
进程池中回调函数callback作用是:进程池中任何一个任务一旦处理完了,就立即告知主进程,主进程则调用一个函数去处理该结果,它可以用来接收进程任务的返回值,判断其执行的结果。
输出结果:
线程1 执行: pid=12372
线程2 执行: pid=11236
线程3 执行: pid=15144
线程4 执行: pid=8332
线程5 执行: pid=16732
线程6 执行: pid=12372
任务1已完成
线程7 执行: pid=11236
任务2已完成
线程8 执行: pid=15144
任务3已完成
线程9 执行: pid=8332
任务4已完成
线程10 执行: pid=16732
任务5已完成
线程11 执行: pid=12372
任务6已完成
线程12 执行: pid=11236
任务7已完成
线程13 执行: pid=15144
任务8已完成
线程14 执行: pid=8332
任务9已完成
线程15 执行: pid=16732
任务10已完成
线程16 执行: pid=12372
任务11已完成
线程17 执行: pid=11236
任务12已完成
线程18 执行: pid=15144
任务13已完成
线程19 执行: pid=8332
任务14已完成
线程20 执行: pid=16732
任务15已完成
任务16已完成
任务17已完成
任务18已完成
任务19已完成
任务20已完成
需要注意的是,在使用线程池时应注意将pool.close() 先于 pool.join() 调用。因为 join() 会让主进程阻塞等待子进程全部执行完之后再执行,close() 的作用是关闭pool,使其不在接受新的(主进程)任务。所以,两个顺序可不能颠倒了。
python学习笔记(九)——线程与进程的更多相关文章
- python学习笔记12 ----线程、进程
进程和线程的概念 进程和线程是操作系统中两个很重要的概念,对于一般的程序,可能有若干个进程,每一个进程有若干个同时执行的线程.进程是资源管理的最小单位,线程是程序执行的最小单位(线程可共享同一进程里的 ...
- python学习笔记11 ----线程、进程、协程
进程.线程.协程的概念 进程和线程是操作系统中两个很重要的概念,对于一般的程序,可能有若干个进程,每一个进程有若干个同时执行的线程.进程是资源管理的最小单位,线程是程序执行的最小单位(线程可共享同一进 ...
- python学习笔记之线程、进程和协程(第八天)
参考文档: 金角大王博客:http://www.cnblogs.com/alex3714/articles/5230609.html 银角大王博客:http://www.cnblogs.com/wup ...
- Python学习笔记九
Python学习笔记之九 为什么要有操作系统 管理硬件,提供接口. 管理调度进程,并且将多个进程对硬件的竞争变得有序. 操作系统发展史 第一代计算机:真空管和穿孔卡片 没有操作系统,所有的程序设计直接 ...
- python学习笔记09--线程、进程
本节内容 一.进程与线程的概念 1.1进程 1.2线程 1.3进程与线程的区别 二.线程 2.1启一个线程 2.2线程的2种调用方式 2.3 join 2.4 守护线程Daemon 2.5线程锁 2. ...
- python学习道路(day10note)(线程,进程)
1.计算机的发展史 看alex的博客吧,了解一下可以了 2.线程与GIL简介 #线程 #一道单一的指令的控制流,寄生在进程中 #单一进程里的多个线程是共享数据的 #多个线程涉及修改共享数据的时候需要枷 ...
- python 学习笔记九 队列,异步IO
queue (队列) 队列是为线程安全使用的. 1.先入先出 import queue #测试定义类传入队列 class Foo(object): def __init__(self,n): self ...
- Python学习笔记9-多线程和多进程
一.线程&进程 对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程, ...
- python学习笔记——multiprocessing 多进程组件 进程池Pool
1 进程池Pool基本概述 在使用Python进行系统管理时,特别是同时操作多个文件目录或者远程控制多台主机,并行操作可以节约大量时间,如果操作的对象数目不大时,还可以直接适用Process类动态生成 ...
- python 学习笔记 - Queue & Pipes,进程间通讯
上面写了Python如何创建多个进程,但是前面文章中创建的进程都是哑巴和聋子,自己顾自己执行,不会相互交流.那么如何让进程间相互说说话呢?Python为我们提供了一个函数multiprocessing ...
随机推荐
- dbeaver安装配置
安装出现库依赖没有,可以添加maven仓库 修改字体:小四
- 量化研究之“大A打板敢死队”是如何做换手板与撬板的?
更多精彩内容,欢迎关注公众号:数量技术宅,也可添加技术宅个人微信号:sljsz01,与我交流. 涨停跌停板分类 涨停.跌停是A股特有的现象,其他主要市场,例如美股.港股都不存在涨跌停的规则.涨停.跌停 ...
- c/c++ 日常积累
基类是抽象类,有(纯)虚函数,子类必须要把所有的都实现啊啊啊!!!!包括子类的析构,你写一个~xx类 = default;也好啊啊啊啊啊啊啊,不然报错!!!!啊啊啊啊啊 流下了悔恨的泪水!!!... ...
- OS模块的补充使用---执行终端命令
Python基础至os模块 由于近期的项目需要用到对应的终端命令去调用其他程序,因此温习一下os.system()函数: 参考文献:https://zhuanlan.zhihu.com/p/51716 ...
- WPF优秀组件推荐之Stylet(一)
一.简介 Stylet是基于WPF的一款MVVM组件,虽然WPF本身是自带MVVM功能的,但实现起来不是很方便 ,通过Stylet,用户可以用很少的代码就能享受MVVM带来的舒适体验. 目前Style ...
- RGBA()函数详解
RGBA()函数详解 RGBA()函数用于设定颜色和颜色的透明度:
- Hystrix&Dashboard配置使用
目录 Hystrix是什么 熔断 什么是熔断 熔断类型 打开 半开 关闭 使用方法 导包 添加启动注解 新增方法 测试 降级 什么是降级 使用方法 导包 修改yml,新增如下 启动类新增注解 @Ena ...
- 基于idea做java程序的本地k8s调试-skaffold(一)
先介绍下本篇文章是基于ideas下开发微服务的场景,大家都知道微服务嘛,一个个微的服务...很多,先不谈调试,要跑起来都费力,可能的原因有: 环境变量的配置,如果多个项目穿插着来,env变量可能废了, ...
- STP详解-STP、RSTP、MSTP
STP详解 01 冗余链路中存在的问题 如图所示LSW1和LSW2之间有两条线路相连,它们之间任何一条链路出现故障另外一条线路可以马上顶替出现故障的那条链路,这样可以很好的解决单链路故障引起的网络中断 ...
- laravel8 登录功能的实现
1.选择合适的框架,渲染出如上图所示的登录视图,视图有样式即可,可使用BootStrap或layUI去布局实现(10分) 2.正确显示出验证码(10分) 3.验证码要求无杂点.无干扰线,4位纯数字(1 ...