python极简教程04:进程和线程
测试奇谭,BUG不见。
大家好,我是谭叔。
这一场,主讲python的进程和线程。
目的:掌握初学必须的进程和线程知识。
进程和线程的区别和联系
终于开始加深难度,来到进程和线程的知识点~
单就这两个概念,就难倒过不少初学者——今天学了概念,明天就忘记;明天学了例子,又忘记了概念。
要理解进程和线程的联系和区别,我举个特简单的例子:
你的电脑有两个浏览器,一个谷歌浏览器,一个qq浏览器。
一个浏览器就是一个进程。
然后,你打开了谷歌浏览器,百度搜索了测试奇谭,又新开一个标签页,打开谭叔的文章,如下图所示:
你可以这样理解——在同一个浏览器打开的两个网页就是两个线程
。如果我关闭了浏览器,这两个线程也没有了。
好了,当你有了概念后,我才好讲两者的区别和联系。
进程
优点
稳定性高
,当程序崩溃后,不影响其他进程的使用。即谷歌浏览器崩溃后,qq浏览器还可以正常使用。
缺点
创建进程的代价大
。即当你开了各种各样的浏览器后,你的电脑会特别卡,因为电脑内存和CPU有上限。
线程
优点
- 多线程通常比多进程快一点,但优势不大
缺点
- 任何一个线程挂掉会造成整个进程崩溃,因为线程共享进程的内存(浏览器的例子不再适用,可以理解为绑在一条船上的蚂蚱)
多进程
因为大多数小伙伴用的Windows操作系统,所以针对Unix/Linux的fork()调用抛开不谈。
在python,一般使用multiprocessing实现多进程。
import os
from multiprocessing import Process
def run_proc(name):
print('开始执行子进程 %s (%s)…' % (name, os.getpid()))
# 子进程要执行的代码
if __name__ == '__main__':
print('父进程 %s.' % os.getpid())
p = Process(target=run_proc, args=('test',)) # 创建一个Process实例
print('子进程即将开始.')
p.start() # 用start()方法启动实例
p.join() # join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步
print('子进程结束.')
要细讲吗?
其实,我的备注写得很全,你只需copy代码下来执行一次,或者debug一次,就能明白。
线程池
如何理解?
即代码可运行的进程数量,有个地方管控它。
from multiprocessing import Pool
import os
import time
import random
def long_time_task(name):
print('开始 task %s (%s)...' % (name, os.getpid()))
start = time.time()
time.sleep(random.random() * 3)
end = time.time()
print('Task %s 执行花费 %0.2f 秒.' % (name, (end - start)))
if __name__ == '__main__':
print('父亲进程 %s.' % os.getpid())
p = Pool(3)
# 因为Pool的默认大小是4,故task 0,1,2,3是立刻执行的,而task 4要等待前面某个task完成后才执行,但最多同时执行4个进程
# 由于Pool的默认大小是CPU的核数,如果你拥有8核CPU,要提交至少9个子进程才能看到等待效果
for i in range(5):
p.apply_async(long_time_task, args=(i,))
print('等待子进程结束...')
p.close()
# 对Pool对象调用join()方法会等待所有子进程执行完毕
# 调用join()之前必须先调用close(),调用close()之后就不能继续添加新的Process了
p.join()
print('所有子进程已执行.')
以上,是必知必会的。
当然,最好的学习时机是:当你要用时,再来复盘学,效果最佳。
如果你学了,没有使用场景,我建议缓一缓学或者作为知识储备。
多线程
多线程有三点必须提前明确:
- 多任务需求可以由多进程完成,也可以由一个进程内的多线程完成
- 进程是由若干线程组成
- 一个进程至少有一个线程
Python的标准库提供了两个模块:_thread和threading,_thread是低级模块,我们一般使用高级模块threading(对_thread进行过封装)。
启动一个线程就是把一个函数传入并创建Thread实例,然后调用start()开始执行,我们看一个简单的例子:
import time
import threading
# 新线程执行的代码
def loop():
# 由于任何进程默认就会启动一个线程,我们把该线程称为主线程,主线程又可以启动新的线程,
# Python的threading模块有个current_thread()函数,它永远返回当前线程的实例
print('线程ss %s 运行中…' % threading.current_thread().name)
n = 0
# 主线程实例的名字叫MainThread,子线程的名字在创建时指定,我们用LoopThread命名子线程,在打印输出的时候显示名字
while n < 5:
n = n + 1
print('线程ss %s >>> %s' % (threading.current_thread().name, n))
time.sleep(1)
print('线程ss %s 已结束.' % threading.current_thread().name)
print('线程 %s is 运行中…' % threading.current_thread().name)
t = threading.Thread(target=loop, name='LoopThread')
t.start()
t.join()
'''
对于 join()方法而言,其另一个重要方面是其实它根本不需要调用。
一旦线程启动,它们 就会一直执行,直到给定的函数完成后退出。
如果主线程还有其他事情要去做,而不是等待这些线程完成(例如其他处理或者等待新的客户端请求),
就可以不调用 join()。join()方法只有在你需要等待线程完成的时候才是有用的
'''
print('线程 %s 已结束.' % threading.current_thread().name)
同样,以上内容,是必知必会的。
并且,工作场景,我们一般会使用多线程处理问题,而非多进程。(注意:是一般)
至于进程间通信、线程锁、GIL锁、多线程变量、线程间通信、异步协程等知识,讲起来比较复杂,也不是极简教程的核心,你可以先自学,或者当你真正要使用它的时候再去看,再去学。
一如既往,做个总结
01 多线程、多进程,是必知必会的;
02 学习进度自己琢磨,既不能死磕,亦不能简单跳过;
03 小伙伴比较关心,面试时会不会被问到。答:一般公司不会,so?
python极简教程04:进程和线程的更多相关文章
- Python 极简教程(八)字符串 str
由于字符串过于重要,请认真看完并保证所有代码都至少敲过一遍. 对于字符串,前面在数据类型中已经提到过.但是由于字符串类型太过于常用,Python 中提供了非常多的关于字符串的操作.而我们在实际编码过程 ...
- python极简教程01:基础变量
测试奇谭,BUG不见. 其实很久之前,就有身边的同事或者网友让我分享一些关于python编程语言的教程,他们同大多数自学编程语言的人一样,无外乎遇到以下这些问题: 网络上的资料过多且良莠不全,不知道如 ...
- python极简教程05:生成器和匿名函数
测试奇谭,BUG不见. 讲解之前,我先说说我的教程和网上其他教程的区别: 1 我分享的是我在工作中高频使用的场景,是精华内容: 2 我分享的是学习方法,亦或说,是指明你该学哪些.该重点掌握哪些内容: ...
- python极简教程07:封装、多态和继承
测试奇谭,BUG不见. 这一场主讲python的面向对象部分--封装.多态和继承. 目的:掌握Python面向对象的三个核心概念. 封装 01 什么是封装? 封装的目的是,保护隐私.通俗的讲:不想让别 ...
- Python 极简教程(一)前言
现在 Python 用处很多,学的人也很多,其流行程度自不必说.但是很多人学 Python 的时候都遇到过问题,特别对于非计算机专业毕业的人来说. 现在的教程非常多,但是绝大部分对于初学者都不够友好. ...
- Python 极简教程(三)数据类型
每种语言都有各种数据类型.这就像在现实生活中,我们计数的时候需要用到数字,在表述金额.重量.距离等需要精确计数时用到小数,在日常交谈中要用文字,等等.在计算机语言中,为了表述不同的情况,也需要用到各种 ...
- Python 极简教程(二)编码工具
Python 的编码工具很多.目前最流行的是 pycharm,关于 pycharm 的安装使用请参考 PyCharm安装使用教程. 而学习过程中,我觉得最好用的,还是 Python 自带的练习工具 I ...
- python极简教程06:生成式和装饰器
测试奇谭,BUG不见. 这一场,主讲python的生成式和装饰器. 目的:掌握四种生成式(列表.生成器.集合.字典),装饰器的原理和使用. 生成式 01 什么是生成式? 能够用一行代码,快速高效的生成 ...
- python极简教程08:对象的方法
测试奇谭,BUG不见. 讲解之前,我先说说我的教程和网上其他教程的区别: 1 我分享的是我在工作中高频使用的场景,是精华内容: 2 我分享的是学习方法,亦或说,是指明你该学哪些.该重点掌握哪些内容: ...
随机推荐
- 共享资源库(Project)
<Project2016 企业项目管理实践>张会斌 董方好 编著 既然要共享资源库,那就得先建一个可供共享的资源库文件,好吧,说得这么高大上,其实就是一个里面只有资源数据的mpp项目文件, ...
- 主要视图展示(Project)
<Project2016 企业项目管理实践>张会斌 董方好 编著 有同学拿Excel做甘特图的(咳咳,我也做过),这行为,其实目的就是为了--消食-- 好吧,也是为了学习Excel中图表或 ...
- 什么是甘特图(Project)
<Project2016 企业项目管理实践>张会斌 董方好 编著 名词解释:"甘特图(Gantt Chart)是一种图形化的项目活动及其他相关系统进度情况的水平方向的条状图.&q ...
- CF275A Lights Out 题解
Content 有一个 \(3\times 3\) 的矩阵.一开始每个元素都为 \(1\). 你可以对任意的位置进行操作,每次操作将在这个位置上的元素及其上下左右的元素全部由 \(1\) 改为 \(0 ...
- CF140D New Year Contest 题解
Content 小 G 想打一场跨年比赛,比赛从下午 \(18:00\) 开始一直持续到次日清晨 \(6:00\),一共有 \(n\) 道题目.小 G 在比赛开始之前需要花费 10 分钟考虑这些题目的 ...
- 【LeetCode】1415. 长度为 n 的开心字符串中字典序第 k 小的字符串 The k-th Lexicographical String of All Happy Strings of Le
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 回溯法 日期 题目地址:https://leetcod ...
- 【LeetCode】453. Minimum Moves to Equal Array Elements 解题报告(Java & Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 方法一:模拟过程 方法二:求和-n*最小值 方法三: ...
- 【LeetCode】697. Degree of an Array 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 求出最短相同子数组度的长度 使用堆求最大次数和最小长 ...
- 【LeetCode】102. Binary Tree Level Order Traversal 二叉树的层序遍历 (Python&C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 BFS DFS 日期 题目地址:https://lee ...
- 如何把 MySQL 备份验证性能提升 10 倍
JuiceFS 非常适合用来做 MySQL 物理备份,具体使用参考我们的官方文档.最近有个客户在测试时反馈,备份验证的数据准备(xtrabackup --prepare)过程非常慢.我们借助 Juic ...