Python编程——多进程与多线程编程(附实例)
进程与线程的概念
进程,是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竟争计算机系统资源的基本单位。每一个进程都有一个自己的地址空间,即进程空间或(虚空间)。进程空间的大小只与处理机的位数有关,一个 16 位长处理机的进程空间大小为216 ,而 32 位处理机的进程空间大小为 232 。进程至少有 5 种基本状态,它们是:初始态,执行态,等待状态,就绪状态,终止状态。
线程,在网络或多用户环境下,一个服务器通常需要接收大量且不确定数量用户的并发请求,为每一个请求都创建一个进程显然是行不通的,无论是从系统资源开销方面或是响应用户请求的效率方面来看。因此,操作系统中线程的概念便被引进了。线程,是进程的一部分,一个没有线程的进程可以被看作是单线程的。线程有时又被称为轻权进程或轻量级进程,也是 CPU 调度的一个基本单位。
进程拥有一个完整的虚拟地址空间,不依赖于线程而独立存在;反之,线程是进程的一部分,没有自己的地址空间,与进程内的其他线程一起共享分配给该进程的所有资源。
1. 多进程(multiprocessing
)
由于Python是跨平台的,自然也提供了一个跨平台的多进程支持。multiprocessing
模块就是跨平台版本的多进程模块。
(1)Process类:
multiprocessing
模块提供了一个Process
类来代表一个进程对象:Process ( target , args ),target表示调用对象,args表示调用对象的位置参数元组。
示例1:创建函数并将其作为单个进程,启动这个子进程并等待其结束;
from multiprocessing import Process
import osdef worker(name):print("子进程是 %s:%s"%(name,os.getpid()))if __name__ == "__main__":print("父进程:%s" %os.getpid())#target表示调用对象,args表示调用对象的位置参数元组。p = Process(target = worker, args = ('p1',))#启动子进程p.start()#等待子进程结束后在继续往下运行,通常用于进程间的同步p.join()print('子进程运行结束!')运行结果:
父进程:948
子进程是 p1:2928
子进程运行结束!
如果没有p.join(),主程序就不会等待子进程运行结束在往下执行,而是会直接运行下面的内容。
from multiprocessing import Process
import osdef worker(name):print("子进程是 %s:%s"%(name,os.getpid()))if __name__ == "__main__":print("父进程:%s" %os.getpid())#target表示调用对象,args表示调用对象的位置参数元组。p = Process(target = worker, args = ('p1',))#启动子进程p.start()print('子进程运行结束!')运行结果:
父进程:5416
子进程运行结束!
子进程是 p1:7480
示例2:创建函数并将其作为多个进程,启动这些子进程并等待其结束;
from multiprocessing import *
import time
import os#子进程1
def worker_1(t):print ("child process1:",os.name,os.getpid())time.sleep(t)print ("end worker_1")
#子进程2
def worker_2(t):print("child process2:", os.name, os.getpid())time.sleep(t)print ("end worker_2")
#子进程3
def worker_3(t):print("child process3:", os.name, os.getpid())time.sleep(t)print ("end worker_3")if __name__ == "__main__":p1 =Process(target = worker_1, args = (4,))p2 =Process(target = worker_2, args = (3,))p3 =Process(target = worker_3, args = (2,))start=time.time()p1.start() #启动子进程1p2.start() #启动子进程2p3.start() #启动子进程3p1.join()p2.join()p3.join()#总消耗时间大致为子进程消耗时间最长的时间:4send=time.time()-startprint("消耗的时间为:",end)
运行结果为:
child process2: nt 6336
child process1: nt 2340
child process3: nt 7992
end worker_3
end worker_2
end worker_1
消耗的时间为: 4.379999876022339
(2)Pool:
如果程序需要启动大量的子进程,就可以采用进程池的方式批量创建子进程。
Pool
对象调用join()
方法会等待所有子进程执行完毕,在调用join()
之前必须先调用close()
,调用close()
之后就表示不能继续添加新的Process
了。
示例1:每个进程消耗的时间为4秒,同时执行5个进程,消耗的总时间大致为8秒;
因为采用 p=Pool() 创建进程池,默认一次执行的进程个数为CPU的核数,我的电脑为4,所以,一次只能执行4个进程,等前四个进程某一个进程结束,在继续第五个进程,(注意:不是四个都结束才进行第五个进程,是四个中的任意一个结束就开始执行个进程);
如下例题,进程0结束后,开始之心进程4;
from multiprocessing import Pool
import time
import os#子进程
def worker(name,t):print ("child process:",name,os.getpid())time.sleep(t)print ("end child process %s"%name)if __name__ == "__main__":print("parent process:",os.getpid())start = time.time()# 创建进程池,默认的个数为CPU的核数,我的电脑为4,表明一次只能同时执行4个进程p=Pool()#执行5个进程for i in range(5):p.apply_async(worker,args=(i,4))#5个进程之后不再添加新的进程对象p.close()p.join()end=time.time()-startprint("消耗的时间为:",end)
运行结果为:
parent process: 7888
child process: 0 1532
child process: 1 6240
child process: 2 5684
child process: 3 1136
end child process 0
child process: 4 1532
end child process 1
end child process 2
end child process 3
end child process 4
消耗的时间为: 8.5
示例2:使用多进程实现股票票价的爬取
#多进程实现股票爬虫
import requests
import re
import time
from multiprocessing import Pool#股票的的代码列表
stock=['300657', '300658', '300659', '300660', '300661', '300662', '300663', '300664', '300665', '300666', '300667', '300668', '300669', '300670']m1=re.compile(r"price: '(.*\..*)'")#获取股票的价格信息
def GetPrice(code):try:url='http://quotes.money.163.com/1%s.html'%codetxt=requests.get(url).textprice=m1.findall(txt)[0]print(code,price)except:passif __name__=="__main__":start = time.time()#创建进程池p=Pool()for code in stock:p.apply_async(GetPrice,args=(code,))p.close()p.join()print("耗时:", time.time() - start)
运行结果为:
300657 40.75
300658 12.4
300659 25.25
300661 81.79
300662 28.85
300660 21.04
300663 17.56
300664 10.4
300665 10.74
300667 27.18
300666 40.62
300669 18.96
300668 18.74
300670 16.55
耗时: 2.3299999237060547
2. 多线程(threading
)
要实现多个任务的并发,可以由多进程完成,也可以由一个进程内的多线程完成。使用多线程类似于同时执行多个不同程序。
示例1:创建函数并将其作为单个线程,启动这个线程并等待其结束;
任何进程默认就会启动一个线程,我们把该线程称为主线程,主线程又可以启动新的线程,Python的
threading
模块有个current_thread()
函数,它永远返回当前线程的实例。主线程实例的名字叫
MainThread
,子线程的名字在创建时指定,我们用childThread
命名子线程。
import time
from threading import *# 线程执行的代码:
def worker():print('thread %s is running' % current_thread().name)n = 0while n < 5:n = n + 1print('thread %s ---> %s' % (current_thread().name, n))time.sleep(1)print('thread %s ended.' % current_thread().name)if __name__=="__main__":start=time.time()#当前线程print('thread %s is running' %current_thread().name)t = Thread(target=worker, name='childThread')#开启线程t.start()#线程结束后回到主程序t.join()print('thread %s ended.' %current_thread().name)end = time.time() - startprint("消耗时间为:", end)
运行结果为:
thread MainThread is running
thread childThread is running
thread childThread ---> 1
thread childThread ---> 2
thread childThread ---> 3
thread childThread ---> 4
thread childThread ---> 5
thread childThread ended.
thread MainThread ended.
消耗时间为: 5.0
示例2:创建函数并将其作为多个线程,启动这些子进程并等待其结束;通过上下两个例子可以发现,最终的耗时都是5秒,所以,线程是同步执行的。
import time
from threading import *# 线程执行的代码:
def worker():print('thread %s is running' % current_thread().name)n = 0while n < 5:n = n + 1print('thread %s ---> %s' % (current_thread().name, n))time.sleep(1)print('thread %s ended.' % current_thread().name)if __name__=="__main__":start=time.time()#当前线程print('thread %s is running' %current_thread().name)t1 = Thread(target=worker, name='childThread1')t2 =Thread(target=worker, name='childThread2')#开启线程t1.start()t2.start()#线程结束后回到主程序t1.join()t2.join()print('thread %s ended.' %current_thread().name)end=time.time()-startprint("消耗时间为:",end)
运行结果为:
thread MainThread is running
thread childThread1 is running
thread childThread1 ---> 1
thread childThread2 is running
thread childThread2 ---> 1
thread childThread1 ---> 2
thread childThread2 ---> 2
thread childThread2 ---> 3
thread childThread1 ---> 3
thread childThread2 ---> 4
thread childThread1 ---> 4
thread childThread2 ---> 5
thread childThread1 ---> 5
thread childThread2 ended.
thread childThread1 ended.
thread MainThread ended.
消耗时间为: 5.0
示例3:使用多线程实现股票票价的爬取;可以与上面用多进程的方式进行比较,时间消耗更少了。
#股票爬虫,多线程
import requests
import re
import time
from threading import Thread#股票的代码
stock=['300657', '300658', '300659', '300660', '300661', '300662', '300663', '300664', '300665', '300666', '300667', '300668', '300669', '300670']m1=re.compile(r"price: '(.*\..*)'")
#获取股票的票价信息
def GetPrice(code):try:url='http://quotes.money.163.com/1%s.html'%codetxt=requests.get(url).textprice=m1.findall(txt)[0]print(code,price)except:passif __name__=="__main__":#创建一个存放线程的列表ts=[]print("开始获取股票的信息....")start = time.time()for code in stock:t=Thread(target=GetPrice,args=(code,))ts.append(t) #添加到线程列表中t.start() #同时开启这个线程for t in ts:t.join() #每个线程执行完成后,再继续执行下面的内容print("股票信息获取成功!")print("耗时:", time.time() - start)
运行结果为:
开始获取股票的信息....
300658 12.4
300657 40.75
300659 25.25
300660 21.04
300664 10.4
300663 17.56
300662 28.85
300661 81.79
300667 27.18
300669 18.96
300666 40.62
300668 18.74
300665 10.74
300670 16.55
股票信息获取成功!
耗时: 0.34999990463256836
Python编程——多进程与多线程编程(附实例)相关推荐
- 一文看懂Python多进程与多线程编程(工作学习面试必读)
进程(process)和线程(thread)是非常抽象的概念, 也是程序员必需掌握的核心知识.多进程和多线程编程对于代码的并发执行,提升代码效率和缩短运行时间至关重要.小编我今天就来尝试下用一文总结下 ...
- Python多进程、多线程编程
文章目录 1. 进程.线程.协程 2. Python多线程 GIL全局解释器锁 CPython科普 3. Python:多进程 or 多线程 计算密集型.I/O密集型科普 4. 编程实战 1. 进程. ...
- Cpython解释器下实现并发编程——多进程、多线程、协程、IO模型
一.背景知识 进程即正在执行的一个过程.进程是对正在运行的程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其他所有内容都 ...
- [PYTHON] 核心编程笔记(18.多线程编程)
18.1 引言/动机 18.2 线程和进程 18.2.1 什么是进程(重量级进程)? 计算机程序只不过是磁盘中可执行的,二进制(或其他类型)的数据,他们只有在被读取到内存中,被操作系统调用时才开始他们 ...
- python多线程编程_python之多线程编程
python 之多线程编程 我们知道 python 中程序一般是从上往下依次执行的,那么即使没有什么联系的两件事也只 能是等一个执行完后再去执行另一个, 这样的就会很浪费时间, 那么有没有办法让两件事 ...
- python 线程锁_python多线程编程(3): 使用互斥锁同步线程
问题的提出 上一节的例子中,每个线程互相独立,相互之间没有任何关系.现在假设这样一个例子:有一个全局的计数num,每个线程获取这个全局的计数,根据num进行一些处理,然后将num加1.很容易写出这样的 ...
- python3多线程编程_Python 3多线程编程学习笔记-基础篇
本文是学习<Python核心编程>的学习笔记,介绍了Python中的全局解释器锁和常用的两个线程模块:thread, threading,并对比他们的优缺点和给出简单的列子. 全局解释器锁 ...
- 多核编程 与 单核多线程编程的区别
本文是阅读周伟民的<多核计算与程序设计>书摘 1.锁竞争: 单核中,如果单个线程取得所,则获取CPU运行时间,其他等待获取锁的线程被阻塞.使用了锁,影响的只是枷锁和解锁的耗时,CPU始终运 ...
- python提高运行效率_提高CPU密集型任务执行效率——Python多进程介绍,内附实例代码...
multiprocessing模块介绍 Python中多线程无法利用多核优势,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程,Python提供了multiprocessi ...
最新文章
- 关于升级 xcode8
- C++ dynamic_cast操作符
- discuz在线人数的实现原理(Discuz6.1.0)
- misc_register、 register_chrdev 的区别总结
- java.util.concurrent 编程范例
- 序列化技术的选型-选型建议
- How is JerryMaster.view.xml being loaded in WebIDE local test environment
- 电脑无法打开特定网页_监理检测网校电脑微信无法打开公路试验检测视频课程的处理方法...
- linux无后缀名程序运行,linux – 如何在Ubuntu上运行无扩展(也许是ELF)文件?
- 别急马上到你们了!携号转网全国推广工作研讨会召开
- python pandas读取csv_pandas读取csv文件数据的方法及注意点
- DP4 最小花费爬楼梯
- Git 更改远程地址
- PDF编辑器哪个好,怎么在PDF中添加图片
- Java .class 反编译 Luyten,导出 .java文件,查看jar 包目录,超级简单,实用
- 大核注意力Large Kernel Attention(LKA)
- 双下划线一粗一细怎么加_word 下划线 一粗一细
- 小程序转发功能的实现(页面转发和按钮转发)
- IDEA 类中找不到main方法请将main方法定义为public static void main. 否则 JavaFX 应用程序类必须扩展javafx.application.Applicati
- python金融量化风险_利用 Python 进行量化投资分析 - 利率及风险资产的超额收益...
热门文章
- undertale人物_Undertale人物实力排名分析(欢迎讨论)
- 组织结构图 的最简单做法
- gitflow概念及上传本地文件到github
- 使用google浏览器添加并翻译英文无字幕视频
- 从零开始学习badusb 7月21日
- 【 C++11 】列表初始化、声明、范围for、STL中一些变化
- cpolra实现内网穿透,无须公网ip
- 学计算机的演员,南开大学计算机系到演员 张桐回顾“不安分”的青春_TOM明星...
- 基于ESP8266与51单片机的震动报警器(车辆报警器)(简单向)
- 以小25倍参数量媲美GPT-3的检索增强自回归语言模型:RETRO