python教程之进程和线程
作者:虚幻私塾 发布时间:2021-09-27 02:54:00
进程和线程的区别和联系
终于开始加深难度,来到进程和线程的知识点~
单就这两个概念,就难倒过不少初学者——今天学了概念,明天就忘记;明天学了例子,又忘记了概念。
要理解进程和线程的联系和区别,我举个特简单的例子:
你的电脑有两个浏览器,一个谷歌浏览器,一个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锁、多线程变量、线程间通信、异步协程等知识,讲起来比较复杂,也不是极简教程的核心,你可以先自学,或者当你真正要使用它的时候再去看,再去学。
来源:https://blog.csdn.net/u013190417/article/details/122445262
猜你喜欢
- 前言Python中的 True和 False总是让人困惑,一不小心就会用错,本文总结了三个易错点,分别是逻辑取反、if条件式和pandas.
- #region 读写xml文件的2个小函数,2005 4 2 by hyc public void 
- 背景介绍Expect 程序主要用于人机对话的模拟,就是那种系统提问,人来回答 yes/no ,或者账号登录输入用户名和密码等等的情况。因为这
- 用div+css制作页面,想实现左右两部分固定宽度,而中间部分不固定,并随着屏幕分辨率的的变化而自动伸缩。大家可知道应该如何实现? &nbs
- 介绍提到爬虫,互联网的朋友应该都不陌生,现在使用Python爬取网站数据是非常常见的手段,好多朋友都是爬取豆瓣信息为案例,我不想重复,就使用
- 如何在网上查找链接? 见下:findlinks.html<html><head>
- 原文地址:30 Days of Mootools 1.2 Tutorials - Day 10 - Using FX.TweenMooToo
- jQuery 真是一个非常伟大的 javascript library,至少在我不会写 JS 的时候第一时间接触了它,虽然还有其他很多优秀的
- python 中提供一种用于对函数固定属性的函数(与数学上的偏函数不一样)# 通常会返回10进制int('12345') &
- 计模式的目的是让代码易维护、易扩展,不能为了模式而模式,因此一个简单的工具脚本是不需要用到任何模式的。简单工厂模式又叫静态工厂方法模式,工厂
- 命名一直是个让我头痛的问题,特别是那些看上去差不多的模块,所以就得想办法啦,我总结了下面的方法,虽然还在试验中。希望对大家有帮助。欢迎大家提
- 英文原文:The seven rules of Unobtrusive JavaScript原文地址:http://icant.co.uk/
- 目录使用软件问题描述搭建神经网络训练参数损失函数参数优化代码数据集参数训练测试结语Hello,兄弟们,开始搞深度学习了,今天出第一篇博客,小
- Apple4.us的张亮问我:“很多人说用户体验是苹果的核心竞争力。在用户体验方面,我究竟该从苹果的设计中学习什么” ?关于这个问题的答案我
- 在我转到wordpress之后第一个考虑的是它的数据库备份恢复问题,因为写bloger都知道,自己的blog记录的都是自己需要的宝贵的资料和
- 到2019年初,Python3已经更新到了Python
- 分区视图联接来自一组成员的水平分区数据,使数据看起来象来自同一张表。SQL Server 2000 区分本地分区视图和分布式分区视图。在本地
- 修改文件的名字 使用“FileSystemObject(文件系统对象)”的GetFile函数得到一个“文件对象”,然后修改这个“文件对象”的
- 1.检查重复元素下面的方法可以检查给定列表中是否有重复的元素。它使用了 set() 属性,该属性将会从列表中删除重复的元素。def all_
- 训练完目标检测模型之后,需要评价其性能,在不同的阈值下的准确度是多少,有没有漏检,在这里基于IoU(Intersection over Un