总第127篇/张俊红

今天我们来聊聊Python里面的多进程与多线程编程模式。

1.多线程工作

在开始讲今天的正文之前,先给大家介绍一个概念「多线程工作」,这个概念可能有的人听过,也可能有的人平常工作中就是这么做的。我再来给大家讲讲这个概念,所谓的「多线程工作」就是同时做好几件事情。

拿我个人工作中例子来说,当我用Sql跑数的时候,数据不可能一下子就导出来,我会在一个屏幕上显示Sql运行进度,在另一个屏幕上先做一会PPT,等Sql跑出来以后,我就又会迅速切换到处理刚刚导出来的数据。有的时候数据量很大,用Excel打开文件可能需要几分钟的时间,这个时候Excel是处于运行状态,我是没法在Excel上做别的事情,我会去微信上去处理别人的一些问题,当文件打开以后,我会迅速切换到Excel上继续下一步处理,当我输入一个公式以后,Excel可能又需要等待一会,这个时候我就可以再去做一些别的事情。

大家可以看到,我没有在等一件事情彻底做完以后再去做另一件事情,而是在不同事情之间迅速切换,这种工作方式就可以算是一种「多线程工作」。

「多线程工作」可以减少你等待的时间,大大提高你的工作效率。

2.多进程与多线程

了解了「多线程工作」以后,我们开始进入今天的正题,编程里面的多线程和多进程。在上面的例子中Sql跑数可以算是一个进程、做PPT也可以算是一个进程、Excel处理数据还是一个进程。

进程下面还有一个更小的单位就是线程,一个进程由若干个线程组成,Sql跑数这个进程可以由写Sql、运行Sql、导出数据这几个线程组成。同样,PPT制作这个进程可以由明确主题、选模板、列大纲、丰富页面这几个线程组成。

线程是程序执行的最小单位,一个进程可以由一个或多个线程组成,各个线程之间也是交叉执行。

这里需要注意的是,多进程/多线程并不能做到同时去做好几件事情,而是把不同的事情交叉着做,做一段时间任务a,然后强制停止,去做一会任务b,再停止,再去做任务c。之所以会觉得各个任务之间是同时进行的原因是是任务与任务之间切换速度足够快,这样看起来就像是多个任务同时在进行。

我们再来看两个概念:

并行:指在同一时刻,有多条指令在多个处理器上同时执行;
并发:指在同一时刻,只能有一条指令执行,但多个进程指令被快速轮换执行,使得在宏观上具有多个进程同时执行的效果。

多份工作有多个人同时在做时就是并行,当多份工作由一个人交替在做时就是并发。在计算机中也是同样的概念,计算机中CPU的核数就相当于人数,当计算机是单核多任务时就是并发;当计算机是多核且大于任务数时,就是并行。目前电脑主流配置都是四核/八线程的,而实际工作的任务数大都大于四个,所以也是需要交替来执行具体任务的,也就是并发执行。

我电脑运行情况

上面就是关于多线程与多进程的一个简单通俗的理解,一些太官方的解释我就不在这里放了,大家感兴趣的可以去自行上网查。

3.多进程与多线程是如何提高效率的

假设做任务A需要1个小时、任务B需要1个小时、任务C需要一个小时,当我们每个任务做20分钟以后切换到另一个任务,这样做完三个任务需要的总时间是不会变的,不仅不会变,反而可能会增加,因为在不同任务之间切换是需要代价的,因为当你从一个任务切换到另一个任务时很有可能不记得刚刚做到哪里了,还需要花时间想一想。那既然是这样,我们为什么还要用多进程/多线程这种处理任务的方式呢?

我在第一小节里面提过,「多线程工作」可以减少你等待的时间,大大提高你的工作效率。是因为在实际工作中,有很多需要等待的地方,比如等待Excel打开,等待Sql跑出数据。多进程/多线程任务处理方式就是充分利用这些等待时间。让你的大脑,计算机的大脑(CPU)得到充分的利用。如果要是没有等待的时间,多进程/多线程的任务处理方式可能就不如单线程的了。

4.多进程与多线程是如何实现的

了解清楚了多进程与多线程是什么,以及是如何提高处理任务的效率的以后,我们进入到硬干货部分,那就是具体多进程/多线程如何实现“同时”处理多任务的。

实现多任务的方式主要有以下几种:

1、多进程模式
2、多线程模式
3、多进程+多线程

同时执行多个任务通常各个任务之间并不是没有关联的,而是需要相互通信和协调,有时,任务1必须暂停等待任务2完成后才能继续执行,有时,任务3和任务4又不能同时执行,所以,多进程和多线程的程序的复杂度要远远高于我们前面写的单进程单线程的程序。

4.1多进程模式

多进程就是一次启动多个进程,每个进程只有一个线程,但多个进程可以一起执行多个任务。一般进程数默认是电脑CPU核数,当你的电脑是四核的时候,你的电脑进程默认就是4个。

4.1.1参数详解

在Python中我们借助多进程包multiprocessing来进行多进程任务处理方式, multiprocessing模块提供了一个Process类来代表一个进程对象,

#Process参数
multiprocessing.Process(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)#group分组
#target表示调用对象,即函数
#name表示进程的别名
#args表示调用对象的位置参数元组,即函数的参数
#kwargs表示调用对象的字典
#Process常用方法
close() 关闭进程
is_alive() 进程是否在运行
join() 等待join语句之前的所有程序执行完毕以后再继续往下运行,通常用于进程间的同步
start()  进程准备就绪,等待CPU调度
run()  strat()调用run方法,如果实例化进程时没有传入target参数,这star执行默认run()方法
#Process常用属性
pid 进程ID
name 进程名字

4.1.2建立一个子进程

下面的例子演示了启动一个子进程(即单进程)并等待其结束:

from multiprocessing import Process
import os# 子进程要执行的代码def run_proc(name):print('Run child process %s (%s)...' % (name, os.getpid()))if __name__=='__main__':print('Parent process %s.' % os.getpid())#用来获取主进程的进程IDp = Process(target=run_proc, args=('test',))#实例化进程p,调用run_proc函数,传入参数对象argsprint('Child process will start.')p.start()#进程准备就绪p.join()#待所有进程执行完毕以后执行后续操作print('Child process end.')

运行结果如下:

Process (876) start...
I (876) just created a child process (877).
I am child process (877) and my parent is 876.

一个子进程其实就和我们平常调用单一函数是一样的。

4.1.3建立多个子进程

建立多个子进程(即多进程),其实就是多个函数随机同步运行。

建立多进程有两种方法,一种是直接利用Process来建立多个子进程即可,如下:

from multiprocessing import Process
import random,timedef do_task(task):print('我正在做{}'.format(task))time.sleep(random.randint(1,3))def write_task(task):print('我正在写{}'.format(task))time.sleep(random.randint(1,3))if __name__ == "__main__":p1 = Process(target=do_task,args=('PPT',))p2 = Process(target=write_task,args=('Sql',))p1.start()p2.start()

输出结果为:

我正在做PPT
我正在写Sql

上面代码表示同时启动两个进程,且两个进程分别调用不同的函数,即做不同的任务。而且上面的任务数只有两个,当任务数(需要调用的函数)较多时,我们如果还用上述的方法创建多进程,就需要实例化多个进程对象,并且写多行p.start()比较麻烦,聪明的前辈们肯定不会用这么笨的方法,所以就有了进程池(Pool)。

multiprocessing.Pool = Pool(processes=None)#process为进程数

把上面的二进程用进程池表示以后的结果如下:

import multiprocessing
import random,timedef do_task(task):print('我正在做{}'.format(task))time.sleep(random.randint(1,3))def write_task(task):print('我正在写{}'.format(task))time.sleep(random.randint(1,3))if __name__ == "__main__":func_list=[do_task,write_task]args_list=["PPT","Sql"]pool=multiprocessing.Pool(2)for func,args in function_list,args_list:pool.apply_async(func,arg)   print 'Waiting for all subprocesses done...'pool.close()pool.join()    #调用join之前,一定要先调用close() 函数,否则会出错print 'All subprocesses done.'

输出结果如下:

Waiting for all subprocesses done...
我正在做PPT
我正在写Sql
All subprocesses done.

4.2多线程模式

多线程模式就是一次只启动一个进程,但是在这个进程里面可以启动多个线程,这样多个线程就可以一起执行多个任务,在Python中我们要启动多线程借助于threading模块,用于 启动多线程的模块还有_thread模块,但是threading模块是封装了_thread模块,且比较高级,所以我们一般使用threading模块即可。

4.2.1参数详解

启动多线程使用的是threading模块中的Thread类,构建时使用的参数和方法与Process基本一致,大家看看即可,这里就不赘述了。

#参数
Thread(group=None, target=None, name=None, args=(), kwargs={})
#方法
isAlive()
get/setName(name) 获取/设置线程名
start()   
join()

4.2.2创建一个线程

创建一个线程就是调用一个函数。

import time, threadingdef do_chioce(task):print('我正在{}'.format(task))time.sleep(random.randint(1,3))if __name__ == "__main__":t = threading.Thread(target=do_chioce,args=('选PPT模板',))t.start()

输出结果为:

我正在选PPT模板

4.2.3创建多个线程

创建多个线程就是调用多个函数。

import time, threadingdef do_chioce(task):print('我正在{}'.format(task))time.sleep(random.randint(1,3))def do_content(task):print('我正在{}'.format(task))time.sleep(random.randint(1,3))if __name__ == "__main__":t1 = threading.Thread(target=do_chioce,args=('选PPT模板',))t2 = threading.Thread(target=do_content,args=('列PPT大纲',))t1.start()t2.start()

输出结果为:

我正在选PPT模板
我正在列PPT大纲

4.3多进程+多线程

多进程+多线程就是一次启动多个进程,每个进程又启动多个线程,这样同时执行的任务就会很多,但是模型相对复杂,不建议使用。

你还可以看:

推荐一款程序员专用的编辑器

推荐一波优质资源

你能分清多进程与多线程吗?相关推荐

  1. python廖雪峰_【Python】python中实现多进程与多线程

    进程与线程 进程(process)就是任务,是计算机系统进行资源分配和调度的基本单位[1].比如,打开一个word文件就是启动了一个word进程. 线程(thread)是进程内的子任务.比如word中 ...

  2. async python两个_【Python】python中实现多进程与多线程

    进程与线程 进程(process)就是任务,是计算机系统进行资源分配和调度的基本单位[1].比如,打开一个word文件就是启动了一个word进程. 线程(thread)是进程内的子任务.比如word中 ...

  3. 多进程和多线程的区别

    多线程和多进程的区别(重点 必须从cpu调度,上下文切换,数据共享,多核cup利用率,资源占用,等等各方面回答,然后有一个问题必须会被问到:哪些东西是一个线程私有的?答案中必须包含寄存器,否则悲催) ...

  4. gunicorn多进程不死_WEB,gunicorn - 无论是多进程、多线程、协程模式,同一个浏览器窗口多个标签页访问同一个url,看上去不会并发的问题...

    TL;DR 其实是浏览器同一个窗口下限制了对同一个url会执行串行操作. 1.参考 2.现象 我有一个WSGI APP,每次处理request都睡眠5秒.不管多进程.多线程.协程跑WSGI APP,同 ...

  5. 一文看懂Python多进程与多线程编程(工作学习面试必读)

    进程(process)和线程(thread)是非常抽象的概念, 也是程序员必需掌握的核心知识.多进程和多线程编程对于代码的并发执行,提升代码效率和缩短运行时间至关重要.小编我今天就来尝试下用一文总结下 ...

  6. 多进程与多线程的区别 - jihite

    多进程与多线程的区别 - jihite 时间 2014-03-16 10:16:00 博客园-所有随笔区 原文  http://www.cnblogs.com/kaituorensheng/p/360 ...

  7. GDB 调试多进程或者多线程应用

    GDB 是 linux 系统上常用的 c/c++ 调试工具, 功能十分强大. 对于较为复杂的系统, 比如多进程系统, 如何使用 GDB 调试呢? 考虑下面这个三进程系统 : 进程 ProcessChi ...

  8. python 多进程和多线程

    python 多进程和多线程 一.进程和线程 1.概念 进程: 一个进程就是一个任务,可以理解为一个程序.一个进程可以有多个线程,至少一个.多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影 ...

  9. 多线程处理同一批数据_多进程和多线程的优缺点

    来源:http://www.cnblogs.com/Yogurshine/p/3640206.html 在Linux下编程多用多进程编程少用多线程编程. IBM有个家伙做了个测试,发现切换线程cont ...

最新文章

  1. 输出程序运行的时间(精确到微秒)
  2. python自动化办公入门书籍推荐-盘点使用Python进行自动化办公所需要的知识点
  3. 七牛2018春季校园招聘后端开发工程师笔试经验
  4. 2021暑假实习-SSM超市积分管理系统-day01笔记
  5. 在 .NET Core 中使用 ViewConfig 调试配置
  6. python语言的语法_PYTHON语言常用语法摘要
  7. strcpy()、memcpy()、memmove()、memset()及其应用
  8. html中鼠标移走的伪元素,a标签的伪元素的应用——link,hover,visited,active
  9. SQL Server中的联合主键、聚集索引、非聚集索引、mysql 联合索引
  10. linux服务器打印400错误,Nginx过一段时间出现400 Bad Request 错误解决方法
  11. 希捷固件门终极解决方法
  12. 常用名词理解(APK,SDK,JDK,API,DLL)
  13. 有道词典与奇迹背单词生词本同步
  14. php 对象教程,创建一个简单的PHP对象_PHP教程
  15. Android开发之实时更新系统时间
  16. 微信群舆情怎么监测?
  17. 射频信号源进阶使用技巧【转载自微信公众号微波射频网】
  18. 7. 全概率公式与贝叶斯公式
  19. jQuery实战读书笔记(第一章至第四章)
  20. 折弯机使用说明书_折弯机基本操作说明

热门文章

  1. QT-Qt获取当前时间并格式化输出及将积秒转换成时间
  2. laravel 缓存相关常用操作
  3. CentOS 7时间命令timedatectl
  4. nginx利用image_filter动态生成缩略图
  5. 《从零开始学Swift》学习笔记(Day 55)——使用try?和try!区别
  6. “Zhuang.Data”轻型数据库访问框架(一)开篇介绍
  7. SNMP在园区企业网络中的应用
  8. jquery的一个代码
  9. 写给找工作的朋友——最典的面试葵花宝典
  10. 第十二章:Java_常用类