[python全栈]06.多线程(2)

目录

  1. 进程对象属性
  2. 自定义进程类
  3. 进程池
  4. 管道通信
  5. 消息队列通信
  6. 共享内存

1. 进程对象属性

Process 进程对象属性
p.start()
p.join() ......
p.is_alive()	判断进程的生命周期状态 返回 True 和 False
p.name	进程名称 默认为 Process-1
p.pid	进程的PID号
p.daemon	默认False 此时主进程退出不会影响子进程执行
		如果设置为True 则子进程会随着主进程结束而结束
		注 : 要在start前设置 , 一般不和join一起使用
from multiprocessing import Process
from time import sleep
#带参数的进程函数
def worker(sec,name):
    for i in range(3):
        sleep(sec)
        print("I'm %s"%name)
        print("I'm working")

p = Process(target = worker,args = (2,),
    kwargs = {"name":"Linux"},name = "worker")
p.start()
print("process name",p.name)
print("process pid: ",p.pid)
print("process is alive",p.is_alive())
p.join()

#daemon.py

from multiprocessing import Process
from time import sleep,ctime

def tm():
    while True:
        sleep(2)
        print(ctime())
p = Process(target = tm)
p.daemon = True
p.start()

sleep(5)
print("main process exit")

2. 自定义进程类

创建自定义进程类 :
	1. 继承Process
	2. 编写自己的 __init__ , 同时加载父类的__init__方法
	3. 重写 run 方法,可以通过生成的对象调用start自动运行
from multiprocessing import Process
import time

class ClockProcess(Process):
    """docstring for ClassName"""
    def __init__(self, value):
        self.value = value
        super().__init__()
    
    #重写run方法
    def run(self):
        for i in range(5):
            print("the time is {}".format(time.ctime()))
            time.sleep(self.value)

#创建自定义进程类的对象
p = ClockProcess(2)
#自动调用run
p.start()
p.join()

3. 进程池

多进程 :
	优点 : 可以使用计算机多核,进行任务的并发进行,提高执行效率
			空间独立,数据安全,运行不受其他进程影响,创建方便
	缺点 : 进程的创建和删除消耗的系统资源较多
	
>>> 进程池技术
产生原因 : 如果有大量的任务需要多进程完成,则可能需要频繁创建删除进程
			给计算机带来较多的资源消耗
原理 : 创建适当的进程放入进程池,用来处理待处理事件
		处理完毕后进程不销毁,仍然在进程池中等待处理其他事件
		进程的复用降低了资源的消耗
使用方法:
	1.创建进程池,在池内放入适当的进程
	2.将时间加入到进程池等待队列
	3.事件不断取进程执行事件,直到所有事件执行完毕
	4.关闭进程池,回收进程
from multiprocessing import Pool
Pool(processes)
	功能 : 创建进程池对象
	参数 : 进程池中有多少进程
	
pool.apply_async(func,arg,kwds) #常用,异步方式
	功能 : 将事件放入到进程池队列
	参数 : func 事件函数
			args 以元组形式给 func 传参
			kwds 以字典形式给func 传参
	返回值 : 返回一个代表进程池时间的对象
			作用 :
pool.apply(func,arg,kwds)	#顺序执行
	功能 : 将事件放入到进程池队列
	参数 : func 事件函数
			args 以元组形式给 func 传参
			kwds 以字典形式给func 传参
			返回值 : 无
pool.map(func,iterable)
	功能 :参考内建map()函数
			将要做的事件放入进程池
	参数 : func 要执行的函数	iterable 可迭代对象
	返回值 : 返回事件函数的返回值列表		
pool.close()	#close()放在join()前,先关闭再回收
	功能 : 关闭进程池
pool.join()
	功能 : 回收进程池
#pool.py
from multiprocessing import Pool
from time import sleep,ctime

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

#创建进程池
pool = Pool(processes = 4)
result = []

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.get())	#i.get() 获取函数对象返回值
#pool_map.py
from multiprocessing import Pool
import time

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

pool = Pool(processes = 4)
#use pool.map()

r = pool.map(fun,range(10))

pool.close()
pool.join()
print(r)

4. 管道通信

进程间通信(IPC) : 
	原因 : 进程空间相对独立,资源无法相互获取
			此时在不同进程间通信间通信需要专门方法
	通信方法: 管道 ;  消息队列 ; 共享内存 ; 信号 ; 信号量 ; 套接字

管道 Pipe :
	通信原理 : 在内存中开辟管道空间,生成管道操作对象
			多个进程使用"同一个"管道对象进行操作,即可实现通信
multiprocessing ---> Pipe
fd1 , fd2 = Pipe(duplex = True)
功能 : 创建管道
参数 : duplex 默认值为True 创建双向管道,False则为单向管道
返回值 : 表示管道的两端
		如果是双向管道,两端都可以读写
		如果是单向管道,则fd1制只读 , fd2只写
fd.recv()
功能 : 从管道读取信息
返回值 : 读取到的内容
	*如果管道为空则阻塞
fd.send()
功能 : 向管道写入内容
参数 : 要写入的内容
	*可以发送python数据类型
#pipe.py
from multiprocessing import Process,Pipe
import os,time

#创建管道对象
fd1,fd2 = Pipe()

def fun(name):
    time.sleep(3)
    #向管道内写入内容
    fd1.send("hello"+str(name))

jobs = []
for i in range(5):
    p = Process(target = fun ,args = (i,))
    jobs.append(p)
    p.start()

for i in range(5):
    #读取管道
    data = fd2.recv()
    print(data)
for i in jobs:
    i.join()

5. 消息队列通信

消息队列
队列 : 先进先出
通信原理 :在内存中建立队列数据结构模型
		多个进程都可以通过队列存入内容
		取出内容的顺序和存入顺序保持一致
创建队列 :
q = Queue(maxsize = 0)
功能 : 创建消息队列
参数 : 表示最多存放多少消息,默认表示根据内存分配存储
返回值 : 队列对象
q.put(data,[block,timeout])
功能:向队列存储消息
参数 : data 要存的内容
		block 默认队列满时会阻塞,设置为False则非阻塞
		timeout 超时时间
data = q.get([block,timeout])
功能 : 获取队列消息
参数 : block 默认队列空时会阻塞,设置为False则非阻塞
		timeout 超时时间
返回值 : 返回取出的内容
q.full()	#判断队列是否为满
q.empty()	#判断队列是否为空
q.qsize()	#判断队列中消息数量
q.close()	#关闭队列
#通过消息队列实现进程间的通信
from multiprocessing import Process,Queue
import time
#创建消息队列
q = Queue()

def fun1():
    time.sleep(1)
    q.put({'a':1,'b':2})
def fun2():
    time.sleep(2)
    print("recv meg: ",q.get())

p1 = Process(target = fun1)
p2 = Process(target = fun2)

p1.start()
p2.start()

p1.join()
p2.join()

6. 共享内存

共享内存 

通信原理:在内存空开辟一块空间,对多个进程可见
		进程可以写入输入,但是每次写入的内容会覆盖之前的内容

obj = Value(ctype,obj)
功能 : 开辟共享内存空间
参数 : ctype  要存储的数据类型
		常用 'i' 整型	'c' 字符串
        obj  共享内存的初始化数据
返回 :共享内存对象

obj.value 即为共享内存值,对其修改即修改共享内存

obj = Array(ctype,obj)
功能 : 开辟共享内存空间
参数 : ctype  要存储的数据格式
        obj  初始化存入的内容 比如列表,字符串	('i',[1,2,3])
	     		如果是整数则表示开辟空间的个数	('i',3) >>> [ , , ]
返回值 : 返回共享内存对象
         * 可以通过遍历过户每个元素的值
	   e.g.  [1,2,3]  ---> obj[1] == 2
         * 如果存入的是字符串
	   obj.value 表示字符串的首地址
#value1.py(Value)
from multiprocessing import Process,Value
import time
import random
#创建共享内存
money = Value('i',2000)

#操作共享内存增加钱数
def deposite():
    for i in range(100):
        time.sleep(0.05)
        #对value属性操作就是操作共享内存
        money.value += random.randint(1,200)
#操作共享内存取钱
def withdraw():
    for i in range(100):
        time.sleep(0.04)
        money.value -=random.randint(1,180)

p1 = Process(target = deposite)
p2 = Process(target = withdraw)

p1.start()
p2.start()

p1.join()
p2.join()

print(money.value)
#Array1.py (Array)
from multiprocessing import Array,Process
import time

#创建共享内存,初始放入列表
#shm = Array('i',[1,2,3,4,5])
#存入字符串
shm = Array('c',b'Hello')
def fun():
    for i in shm:
        print(i)
    shm[0] = b'h'
p = Process(target = fun)
p.start()
p.join()
for i in shm:
    print(i)
print(shm.value)    #打印字符串 >>> 'hello'

总结

           管道(Pipe)		消息队列(Queue)		共享内存(Value/Array)
开辟空间		内存				内存				内存

读写方式		两端读写				先进先出			覆盖之前内容
           双向/单向

效率		一般				 一般				较高

应用		多用于父				广泛灵活				需要注意
			子进程									进行互斥操作

复习 :

1. 回顾进程间通信方法
2. 复习类的使用
3. 对进程使用和原理进行总结
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值