进程与线程的概念

进程,是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竟争计算机系统资源的基本单位。每一个进程都有一个自己的地址空间,即进程空间或(虚空间)。进程空间的大小只与处理机的位数有关,一个 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编程——多进程与多线程编程(附实例)相关推荐

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

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

  2. Python多进程、多线程编程

    文章目录 1. 进程.线程.协程 2. Python多线程 GIL全局解释器锁 CPython科普 3. Python:多进程 or 多线程 计算密集型.I/O密集型科普 4. 编程实战 1. 进程. ...

  3. Cpython解释器下实现并发编程——多进程、多线程、协程、IO模型

    一.背景知识 进程即正在执行的一个过程.进程是对正在运行的程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其他所有内容都 ...

  4. [PYTHON] 核心编程笔记(18.多线程编程)

    18.1 引言/动机 18.2 线程和进程 18.2.1 什么是进程(重量级进程)? 计算机程序只不过是磁盘中可执行的,二进制(或其他类型)的数据,他们只有在被读取到内存中,被操作系统调用时才开始他们 ...

  5. python多线程编程_python之多线程编程

    python 之多线程编程 我们知道 python 中程序一般是从上往下依次执行的,那么即使没有什么联系的两件事也只 能是等一个执行完后再去执行另一个, 这样的就会很浪费时间, 那么有没有办法让两件事 ...

  6. python 线程锁_python多线程编程(3): 使用互斥锁同步线程

    问题的提出 上一节的例子中,每个线程互相独立,相互之间没有任何关系.现在假设这样一个例子:有一个全局的计数num,每个线程获取这个全局的计数,根据num进行一些处理,然后将num加1.很容易写出这样的 ...

  7. python3多线程编程_Python 3多线程编程学习笔记-基础篇

    本文是学习<Python核心编程>的学习笔记,介绍了Python中的全局解释器锁和常用的两个线程模块:thread, threading,并对比他们的优缺点和给出简单的列子. 全局解释器锁 ...

  8. 多核编程 与 单核多线程编程的区别

    本文是阅读周伟民的<多核计算与程序设计>书摘 1.锁竞争: 单核中,如果单个线程取得所,则获取CPU运行时间,其他等待获取锁的线程被阻塞.使用了锁,影响的只是枷锁和解锁的耗时,CPU始终运 ...

  9. python提高运行效率_提高CPU密集型任务执行效率——Python多进程介绍,内附实例代码...

    multiprocessing模块介绍 Python中多线程无法利用多核优势,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程,Python提供了multiprocessi ...

最新文章

  1. 关于升级 xcode8
  2. C++ dynamic_cast操作符
  3. discuz在线人数的实现原理(Discuz6.1.0)
  4. misc_register、 register_chrdev 的区别总结
  5. java.util.concurrent 编程范例
  6. 序列化技术的选型-选型建议
  7. How is JerryMaster.view.xml being loaded in WebIDE local test environment
  8. 电脑无法打开特定网页_监理检测网校电脑微信无法打开公路试验检测视频课程的处理方法...
  9. linux无后缀名程序运行,linux – 如何在Ubuntu上运行无扩展(也许是ELF)文件?
  10. 别急马上到你们了!携号转网全国推广工作研讨会召开
  11. python pandas读取csv_pandas读取csv文件数据的方法及注意点
  12. DP4 最小花费爬楼梯
  13. Git 更改远程地址
  14. PDF编辑器哪个好,怎么在PDF中添加图片
  15. Java .class 反编译 Luyten,导出 .java文件,查看jar 包目录,超级简单,实用
  16. 大核注意力Large Kernel Attention(LKA)
  17. 双下划线一粗一细怎么加_word 下划线 一粗一细
  18. 小程序转发功能的实现(页面转发和按钮转发)
  19. IDEA 类中找不到main方法请将main方法定义为public static void main. 否则 JavaFX 应用程序类必须扩展javafx.application.Applicati
  20. python金融量化风险_利用 Python 进行量化投资分析 - 利率及风险资产的超额收益...

热门文章

  1. undertale人物_Undertale人物实力排名分析(欢迎讨论)
  2. 组织结构图 的最简单做法
  3. gitflow概念及上传本地文件到github
  4. 使用google浏览器添加并翻译英文无字幕视频
  5. 从零开始学习badusb 7月21日
  6. 【 C++11 】列表初始化、声明、范围for、STL中一些变化
  7. cpolra实现内网穿透,无须公网ip
  8. 学计算机的演员,南开大学计算机系到演员 张桐回顾“不安分”的青春_TOM明星...
  9. 基于ESP8266与51单片机的震动报警器(车辆报警器)(简单向)
  10. 以小25倍参数量媲美GPT-3的检索增强自回归语言模型:RETRO