多任务编程之进程Process

进程

(1)进程

  • 程序在计算机中的一次计算过程,是一个动态的过程描述,进程是占有计算机资源的,有一定生命周期

(2)程序

  • 是一个可执行文件,是静态的,占有磁盘,不占计算机的运行资源

(3)注意

  • 同一个程序的不同运行过程是不同的进程,因为分配的计算机资源不同,生命周期也不同

(4)进程创建流程

  1. 用户空间运行一个程序,发起进程的创建
  2. 操作系统接受用户申请,开启进程创建
  3. 操作系统分配计算机资源,确定进程创建状态
  4. 将新创建的进程交给用户使用

(5)CPU时间片

(1)定义

  • 如果一个进程占有计算机核心,我们称为该进程占有CPU时间片
  • 多个任务实际会对CPU内核进行争夺,由操作系统分配CPU资源

(6)进程信息

  1. pcb(进程控制块)
            在*nux操作系统中,进程创建后会自动在内存中产生一个会计存放进程信息,称为PCB
  2. 内容
            进程ID、进程占有内存位置、创建时间、创建用户…
  3. 查看命令
            ps -aux
            PID(进程编号):在操作系统中进程的唯一标志,大于0的整数,由系统自动分配
           %CPU(CPU占有率)
           %MEM(内存占有率)
           STAT(进程状态)

(7)进程的特征

  1. 进程是操作系统分配计算机资源的最小单位
  2. 每个进程有自己单独的虚拟内存空间(4G)
  3. 进程之间的执行上相互独立,互不影响

(8)进程的状态

  1. 三态
    在这里插入图片描述
  • 就绪态:进程具备执行条件,等待系统分配处理器资源
  • 运行态:进程占有CPU处于运行的状态
  • 等待态:进程暂时不具备运行条件,需要阻塞等待
  1. 五态
    在这里插入图片描述
  • 在三态基础上增加了新建态和终止态
  • 新建态:创建一个新的进程,获取资源的过程
  • 终止态:进程执行结束,资源释放回收的过程
  • ps -aux------------>STAT(进程状态)
  • D:等待态(不可中断等待)
  • S:等待态(可中断等待)
  • T:等待态(暂停状态)
  • R:运行态(包含就绪态)
  • Z:僵尸态(进程结束)
  • + :前台进程,在终端运行
  • < :高优先级
  • N :低优先级
  • l :有进程链接
  • S :会话组

(9)进程优先级

  • 优先级决定了一个进程的执行权限和占有资源的优先程度

(1)查看优先级:

top  
  • 动态查看进程优先级 按<>翻页
  • q 退出

(2)优先级取值范围

  • -20-----------19                    -20(最高)

(3)指定的优先级来运行程序

nice -9 ./while.py
nice --9 ./while.py   -9的优先级运行

(10)创建进程流程

  1. 创建进程对象
import multiprocessing

p = multiprocessiong.Process()
  • 功能:创建进程对象
  • 参数:
  • name:给创建的进程对象起一个名字,默认为process -1
  • target:绑定的函数
  • args:元组,用来给target函数传参,按照位置传参
  • kwargs:字典,按照键值传参{name:“Alex”}
  1. 启动进程,进程被创建,自动运行对应函数
p.start()
  1. 回收子进程
p.join([timeout])
  • 功能:阻塞等待对应子进程的退出,回收子进程
  • 参数:超时时间

(11)进程对象属性

  1. p.join() 回收进程
  2. p.start() 启动并创建进程
  3. p.is_alive() 判断进程是否在生命周期状态,在生命周期状态返回True,否则返回False
  4. p.name 进程名称,默认为process-1,如果起名字则为自己取得名称
  5. p.pid 进程pid
  6. p.daemon 默认为False,主进程退出不影响子进程,如果设置为True则主进程退出时会让所有子进程都退出
p.daemon = True
  • 该属性设置必须在start( )前
  • 该属性一般不用和join同时出现
import multiprocessing as mp
from time import sleep

# 带参数的事件函数
def worker(sec,name):
	for i in range(3):
        # 等待主进程先打印进程信息
		sleep(sec)
		print("I am %s" % name)
		print("I am working....")

# 通过args, kwargs进行参数传递
p = mp.Process(name="worker", target=worker, args=(2,),
			kwargs={"name":"Alex"})
p.start()

# 进程状态
s = p.is_alive()
print("is alive", s)

# 进程名称
print("Process name", p.name)

# 进程pid
print("Process pid", p.pid)

p.join(4)
print("===================")

运行结果

ubantu@ubantu-virtual-machine:~/Process_mode$ python3 pool.py 
is alive True
Process name worker
Process pid 14646
I am Alex
I am working....
I am Alex
I am working....
===================
I am Alex
I am working....

(12)说明

  1. 如果不使用 join则子进程会变成僵尸进程
  2. 在使用Multiprocessing创建进程过程中,一般父进程功能就是创建子进程等待回收,不做其他过多事情
  3. 使用Multiprocessing创建子进程,同样进程复制父进程空间,之后有自己独立执行空间,互不干扰

(13)代码示例

from multiprocessing import Process
from time import sleep
import os


def th1():
	sleep(3)
	print("吃饭")
	print(os.getppid(),"----",os.getpid())
def th2():
	sleep(2)
	print("睡觉")
	print(os.getppid(),"----",os.getpid())
def th3():
	sleep(4)
	print("打豆豆")
	print(os.getppid(),"----",os.getpid())

process=[]

thing = [th1,th2,th3]

for th in thing:
	# 循环创建进程
	p = Process(target=th)
	# 将进程对象保存
	process.append(p)
	p.start()

# 回收进程
for i in process:
	i.join()

运行结果

ubantu@ubantu-virtual-machine:~/Process_mode$ python3 01_process.py 
睡觉
14171 ---- 14173
吃饭
14171 ---- 14172
打豆豆
14171 ---- 14174
ubantu@ubantu-virtual-machine:~/Process_mode$

(14)继承Process创建自己的线程类

(1)流程

  1. 继承Thread类
  2. 运行Thread类中的__init__方法,以获取父类原有的属性
  3. 重写run方法
import multiprocessing as mp
import time

class MyProcess(mp.Process):
	def __init__(self, target, name='', args=(), kwargs={}):
		super().__init__()
		self.name = name
		self.target = target
		self.args = args
		self.kwargs = kwargs
	
	def run(self):
		self.target(*self.args)

def palyer(song, times, sec):
	for i in range(times):
		print('playig %s : %s' % (song, time.ctime()))
		time.sleep(sec)

if __name__ == "__main__":
	p_list = []
	p = MyProcess(target=palyer, args=('爱我中华', 10, 1))
	p.start()
	p_list.append(p)
	p2 = MyProcess(target=palyer, args=('一起摇摆', 5, 1))
	p2.start()
	p_list.append(p2)
	for i in p_list:
		i.join()

运行结果

ubantu@ubantu-virtual-machine:~/Process_mode$ python3 02_process.py 
playig 爱我中华 : Tue Apr  2 17:39:53 2019
playig 一起摇摆 : Tue Apr  2 17:39:53 2019
playig 爱我中华 : Tue Apr  2 17:39:54 2019
playig 一起摇摆 : Tue Apr  2 17:39:54 2019
playig 爱我中华 : Tue Apr  2 17:39:55 2019
playig 一起摇摆 : Tue Apr  2 17:39:55 2019
playig 爱我中华 : Tue Apr  2 17:39:56 2019
playig 一起摇摆 : Tue Apr  2 17:39:56 2019
playig 爱我中华 : Tue Apr  2 17:39:57 2019
playig 一起摇摆 : Tue Apr  2 17:39:57 2019
playig 爱我中华 : Tue Apr  2 17:39:58 2019
playig 爱我中华 : Tue Apr  2 17:39:59 2019
playig 爱我中华 : Tue Apr  2 17:40:00 2019
playig 爱我中华 : Tue Apr  2 17:40:01 2019
playig 爱我中华 : Tue Apr  2 17:40:02 2019

(15)进程优缺点

  1. 优点

         并行执行多个任务,提高效率,创建方便

         运行独立,不受其他进程影响数据安全

  1. 缺点

         在进程创建和删除过程中消耗计算机资源较多

(16)进程池技术

  1. 目的
  • 一次性创建多个进程,将要做的事加入进程池,做完一批事情后,再将剩下的事加入,以此类推,直到所有事情做完后,再将进程销毁,使得进程可以得到充分的利用,节省资源
  1. 产生原因
  • 如果有大量的任务需要多进程完成,则可能需要频繁的创建和删除进程,给计算机带来更多消耗
  1. 使用场景
  • 大量可以短时间完成的任务,需要多进程操作时,比较适用进程池
  1. 使用方法

(1)创建进程池,在池内放入适当的进程

from multiprocessing import Pool

pool=Pool(processes=n)
  • 功能:创建进程池对象
  • 参数:表示进程池中有多少进程
  • 对象:得到进程池对象

(2)将事件加入进程池队列

# 异步将事件放入进程池
# 一次执行放入对等个数的事件(一次执行多个)

pool.apply_async(func, args, kwds)
  • 功能:将事件放入进程池等待执行
  • 参数:func 要放入进程池的事件函数
               args 给func函数以元组传参
               Kwds 给func函数以字典传参
  • 返回值:返回一个事件对象,通过get( )方法可以获取到事 件函数的返回值
# 同步将事件放入进程池
# 放入事件一个执行完后再执行另一个(一个一个执行)

pool.apply (func, args, kwds) 
  • 功能:将事件放入进程池等待执行
  • 参数:func 要放入进程池的事件函数
               args 给func函数以元组传参
               Kwds 给func函数以字典传参
  • 返回值:没有返回值
pool.map( func, iter )
  • 功能:将事件放入进程池等待执行
  • 参数:func:要完成的事件函数
               iter: 要给func传递参数的迭代器
  • 返回值:返回事件函数的返回值列表

(3)进程事件不断运行,直到所有事件运行完成
(4)关闭进程池,回收进程

pool.close()
pool.join()

5. 示例演示

from multiprocessing import Pool
from time import sleep, ctime

def worker(msg):
	sleep(2)
	print(msg)
	return ctime()

if __name__ == "__main__":
	result=[]

	# 创建进程池对象
	pool = Pool(processes=4)

	for i in range(10):
		msg = "hello %d" % i
		# 将事件加入到进程池
		r = pool.apply_async(func=worker, args=(msg,))
		result.append(r)

	# 关闭进程池
	pool.close()
	# 回收进程
	pool.join()

	for i in result:
		print(i)
	    # 获取到事件函数的返回值
		print(i.get())

运行结果
在这里插入图片描述

from multiprocessing import Pool
from time import sleep, ctime

def worker(msg):
	sleep(2)
	print(msg)
	return ctime()

if __name__ == "__main__":
	# 创建进程池对象
	pool = Pool(processes=4)

	for i in range(10):
		msg = "hello %d" % i
		# 将事件加入到进程池
		r = pool.apply(func=worker, args=(msg,))
		result.append(r)

	# 关闭进程池
	pool.close()
	# 回收进程
	pool.join()

运行结果
在这里插入图片描述

from multiprocessing import Pool
import time


def fun(n):
	time.sleep(1)
	print("执行pool map事件", n)
	return n*n
	
pool = Pool(4)

# map放入6个事件到进程池中
# r:事件函数返回值列表
r = pool.map(fun, range(6))

print("返回值列表", r)

pool.close()
pool.join()

运行结果
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值