2021-10-15 python从入门到精通--第十八章 进程和线程

使用进程和线程

进程

创建进程

使用multiprocessing模块创建进程
Process([group [, target [, name [, args [, kwargs]]]]])

group:参数未使用,值始终未None
target:表示当前进程启动时执行的可调用对象
name:表示当前进程实例的别名
args:表示传递给target函数的参数元组
kwargs:表示传递给targe函数的参数字典
例:

form multiprocessing import Process

def test(interval):
	print("我是子进程")
def main():
	print("主进程开始")
	p=Process(target=test, args = (1, ))
	p.start()
	print("主进程结束")

if __name__ == "main":
	main()
  • is_alive():判断进程实例是否还在执行
  • join([timeout]):等待进程实例执行结束,等待多少秒
  • start():启动进程实例
  • run():如果没有给定target参数,对这个对象调用start()方法时,则执行对象中的run方法
  • terminate():立即终止
  • name:当前进程实例别名
  • pid:当前进程实例的PID值
使用Process子类创建进程

对于简单任务,通常使用Process(target = test)方式实现多进程
处理复杂任务,通常定义一个类,继承Process类

from multiprocessing import Process
import time
import os

#继承Process类
class SubProcess(Process):
	#重写了父类的__init__()方法
	def __init__(self, interval, name = ""):
		Process.__init__(self)  #调用Process父类的初始化方法
		self.interval = interval #追加了自己的内容
		if name:
			self.name = name
	#重新了run()方法
	def run(self):
		t_start = time.time()
		time.sleep(self.interval)
		t_stop = time.time()
  
if __name__ = "__main__":
	p1 = SubProcess(interval = 1, name = "mrsoft")
	p2 = SubProcess(interval = 2)
	p1.start()  #启动进程p1
	p2.start()  #启动进程P2
	p1.join()  #等待p1进程结束
	p2.join()  #等待p2进程结束
使用进程池Pool创建进程

创建多个进程时,使用multiprocess模块中的pool类

  • apply_async(func[, ags[, kwds]]):非阻塞方式调用func函数,args为传递func函数的参数列表,kwds为传递给func函数的关键字参数列表
  • apply(func[, args[, kwds]]):阻塞方式调用func函数
  • close():关闭pool,使其不再接收新任务
  • terminate():立即终止
  • join():主进程阻塞,等待子进程退出,必须在close或terminate之后使用
from multiprocessing import Pool
import os, time

def task(name):
	print("子进程%s 执行task %s"%(os.getpid(), name))
	time.sleep(1)

if __name__ = "__main__":
	p = Pool(3)
	for i in range(10):
		p.apply_async(task, args(i,))
	p.close()
	p.join()

进程间通信

队列

先进先出

多进程队列的使用

可以使用multiprocessing模块的Queue实现多进程间的数据传递

  • q = Queue(num):初始化,若num为0或负数,代表接收的消息数量没有上限
  • q.qsize():返回当前队列包含的消息数量
  • q.empty():判断队列是否为空,为空则返回True
  • q.full():判断队列是否已满,已满则会True
  • q.get([block[, timeout]]):获取队列中的消息,block默认是True
    block = True && 未设置timeout:消息队列为空时阻塞在读取状态
    block = True && 设置timeout:timeout时间若消息队列未空则抛Queue.Empty异常
    block = False:消息队列未空则立刻抛Queue.Empty异常
  • q.get_nowait():相当于q.get(False)
  • q.put(item, [block[, timeout]]):将item消息写入队列,block默认时True
    block = True && 未设置timeout:消息队列无空间可写时阻塞在写入状态
    block = True && 设置timeout:等待timeout,如果还没有空间则抛Queue.Full异常
    block = False:消息队列无空间可写时立即抛Queue.Full异常
  • q.put_nowait(item):相当于q.put(item, False)

例:

from multiprocessing import Queue

if __name__ = "__main__":
	q = Queue(3)
	q.put("message1")
	q.put("message2")
	q.put("message3")

	try:
		q.put("message4", True, 2)
	except:
		print("Queue Full,count:%s"%q.qsize())

	if not q.empty():
		for i in range(q.size()):
		print(q.get_nowait())

	if not q.full():
		q.put_nowait("message4")
使用队列在进程间通信

例:

from multiprocessing import Process, Queue
import time

def write_task(q):
	if not q.full():
		for i in range(5):
			message = "msg" + str(i)
			q.put(message)
def read_task(q):
	time.sleep(1)
	while not q.empty():
		print(q.get(True, 2))

if __name__ = "__main__":
	q = Queue()
	pw = Process(target = write_task, args = (q, ))
	pr = Process(target = read_task, args(q, ))
	pw.start()
	pr.start()
	pw.join()
	pr.join()

线程

创建线程

使用threading模块创建线程
Thread([group [, target [, name [, args [, kwargs]]]]])
  • group:值恒为None
  • target:表示一个可调用对象,线程启动时,run()方法将调用此对象
  • name:表示当前线程名称
  • args:表示传递给target函数的参数元组
  • kwargs:表示传递给target函数的参数字典

例:

import threading, time

def process():
	for i in range(3):
		time.sleep(1)
		priint("thread name is %s"%threading.current_thread().name)

if __name__ = "__main__":
	threads = [threading.Thread(target = process) for i in range(4)] #创建4个线程,存入列表
	for t in threads:
		t.start()  #开启线程
	for t in threads:
		t.join()  #等待子线程结束
使用Thread子类创建线程
import threading, time

#创建子类SubThread,继承threading.Thread线程类,实例化线程,会自动调用父类的__init__()方法
class SubThread(threading.Thread):
	def run(self):
		for i in range(3):
			time.sleep(1)
			msg = "子线程" + self.name + str(i)  #name中保存的是当前线程的名字
			print(msg)

if __name__ = "__main__":
	t1 = SubThread()
	t2 = SubThread()
	t1.start()
	t2.start()
	t1.join()
	t2.join()

线程间通信

线程间共享全局变量

互斥锁

由于所有线程都可以随意更改全局变量,需要使用互斥锁,防止多个线程同时访问同一片内存

使用互斥锁

Lock类中有两个方法,acquire()锁定和release()释放

mutex = threading.Lock()		#创建锁
mutex.acquire([blocking])	#锁定
mutex.release()			#释放
使用队列在线程间通信

与进程中队列的使用方法相同

from queue import Queue
import random, threading, time

class Producer(threading.Thread):
	def __init__(self, name, queue):
		threading.Thread.__init__(self.name = name)
		self.data = queue
	def run(self):
		for i in range(5):
			print("%s, %d"%(self.getName(), i))
			self.data.put(i)
			time.sleep(random.random())

class Consumer(threading.Thread):
	def __init__(self, name, queue):
		threading.Thread.__init__(self, name = name)
		self.data = queue
	def run(self):
		for i in range(5):
			val = self.data.get()
			print("%s, %d"%(self.getName(), val))
			time.sleep(random.random())

if __name__ == "__main__":
	queue = Queue()
	producer = Producer("Producer", queue)
	consumer = Consumer("Consumer", queue)
	producer.start()
	consumer.start()
	producer.join()
	consumer.join()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值