import os
import time
def do_sth(name):
"""进程做的事情"""
print("进程的名称:{} PID: {}".format(name, os.getpid()))
time.sleep(10)
print('进程要做的事情')
if __name__ =="__main__":
p1 = Process(target=do_sth, args=('p1',))
p2 = Process(target=do_sth, args=('p2',))
# 启动进程
p1.start()
p2.start()
p1.join()
p2.join()
输出为:
进程的名称:p1 PID: 6700
进程的名称:p2 PID: 7364
进程要做的事情
进程要做的事情
使用Queue和Pipes实现进程之间 的通信,以下为Queue的使用案例。
import os
import time
from multiprocessing import Process, Queue
class WriteProcess(Process):
# 要写的内容
ls = [
"第一行",
"第二行",
"第三行",
"第四行"
]
def __init__(self, q, *args, **kwargs):
super().__init__()
self.q = q
def run(self):
for line in self.ls:
print("write: {}".format(line))
self.q.put(line)
time.sleep(1)
class ReadProcess(Process):
def __init__(self, q, *args, **kwargs):
super().__init__()
self.q = q
def run(self):
while True:
print(self.q.get())
if __name__ =="__main__":
q = Queue()
w = WriteProcess(q)
r = ReadProcess(q)
w.start()
r.start()
w.join()
r.terminate() # 终止读操作进程,因为读操作进程执行死循环
输出为:
write: 第一行
第一行
write: 第二行
第二行
write: 第三行
第三行
write: 第四行
第四行
import time
from multiprocessing import Process, Lock
class WriteProcess(Process):
"""写入文件"""
def __init__(self, file_name, num, lock, *args, **kwargs):
self.file_name = file_name
super().__init__(*args, **kwargs)
self.num = num
self.lock = lock
def run(self):
"""写入文件业务逻辑"""
try:
# self.lock.acquire() # 关闭进程锁
for i in range(5):
with open(self.file_name, 'a+', encoding='utf-8') as f:
content = '现在是:{}:{}-{}\n'.format(self.name, self.pid, self.num)
f.write(content)
time.sleep(0.5)
print(content)
finally:
# self.lock.release()
pass
if __name__ == "__main__":
file_name = 'test.txt'
lock = Lock()
for x in range(5):
p = WriteProcess(file_name, x, lock)
p.start()
输出为:
现在是:WriteProcess-3:9308-2
现在是:WriteProcess-1:13764-0
现在是:WriteProcess-4:13380-3
现在是:WriteProcess-2:8180-1
现在是:WriteProcess-5:9564-4
现在是:WriteProcess-3:9308-2
现在是:WriteProcess-1:13764-0
现在是:WriteProcess-4:13380-3
现在是:WriteProcess-5:9564-4
现在是:WriteProcess-2:8180-1
现在是:WriteProcess-3:9308-2
现在是:WriteProcess-1:13764-0
现在是:WriteProcess-4:13380-3
现在是:WriteProcess-2:8180-1
现在是:WriteProcess-3:9308-2
现在是:WriteProcess-1:13764-0
现在是:WriteProcess-4:13380-3
现在是:WriteProcess-2:8180-1
现在是:WriteProcess-5:9564-4
现在是:WriteProcess-3:9308-2
现在是:WriteProcess-1:13764-0
现在是:WriteProcess-4:13380-3
现在是:WriteProcess-5:9564-4
现在是:WriteProcess-2:8180-1
import time
from multiprocessing import Process, Lock
class WriteProcess(Process):
"""写入文件"""
def __init__(self, file_name, num, lock, *args, **kwargs):
self.file_name = file_name
super().__init__(*args, **kwargs)
self.num = num
self.lock = lock
def run(self):
"""写入文件业务逻辑"""
try:
self.lock.acquire()
for i in range(5):
with open(self.file_name, 'a+', encoding='utf-8') as f:
content = '现在是:{}:{}-{}\n'.format(self.name, self.pid, self.num)
f.write(content)
time.sleep(0.5)
print(content)
finally:
self.lock.release()
if __name__ == "__main__":
file_name = 'test.txt'
lock = Lock()
for x in range(5):
p = WriteProcess(file_name, x, lock)
p.start()
输出为:
现在是:WriteProcess-3:7876-2
现在是:WriteProcess-3:7876-2
现在是:WriteProcess-3:7876-2
现在是:WriteProcess-3:7876-2
现在是:WriteProcess-3:7876-2
现在是:WriteProcess-4:11456-3
现在是:WriteProcess-4:11456-3
现在是:WriteProcess-4:11456-3
现在是:WriteProcess-4:11456-3
现在是:WriteProcess-4:11456-3
现在是:WriteProcess-1:12440-0
现在是:WriteProcess-1:12440-0
现在是:WriteProcess-1:12440-0
现在是:WriteProcess-1:12440-0
现在是:WriteProcess-1:12440-0
现在是:WriteProcess-2:8596-1
现在是:WriteProcess-2:8596-1
现在是:WriteProcess-2:8596-1
现在是:WriteProcess-2:8596-1
现在是:WriteProcess-2:8596-1
现在是:WriteProcess-5:10656-4
现在是:WriteProcess-5:10656-4
现在是:WriteProcess-5:10656-4
现在是:WriteProcess-5:10656-4
现在是:WriteProcess-5:10656-4
import time
from multiprocessing import Pool, current_process
def run(file_name, num):
with open(file_name, 'a+', encoding='utf-8') as f:
now_process = current_process()
# 写入的内容
content = "{} - {} - {}\n".format(
now_process.name,
now_process.pid,
num
)
print(content)
f.write(content)
time.sleep(1)
return 'OK'
if __name__ == "__main__":
pool = Pool(5)
file_name = 'text_pool.txt'
for i in range(10):
# 同步执行
rest = pool.apply(run, args = (file_name, i))
# 异步执行
# rest = pool.apply_async(run, args=(file_name, i))
print("{1} - {0}".format(rest, i))
pool .close()
pool.join()
同步执行结果:
SpawnPoolWorker-2 - 13144 - 0
0 - OK
SpawnPoolWorker-4 - 10136 - 1
1 - OK
SpawnPoolWorker-1 - 13056 - 2
2 - OK
SpawnPoolWorker-3 - 12296 - 3
3 - OK
SpawnPoolWorker-5 - 13612 - 4
4 - OK
SpawnPoolWorker-2 - 13144 - 5
5 - OK
SpawnPoolWorker-4 - 10136 - 6
6 - OK
SpawnPoolWorker-1 - 13056 - 7
7 - OK
SpawnPoolWorker-3 - 12296 - 8
8 - OK
SpawnPoolWorker-5 - 13612 - 9
9 - OK
异步执行结果为:
0 -
1 -
2 -
3 -
4 -
5 -
6 -
7 -
8 -
9 -
SpawnPoolWorker-2 - 11344 - 0
SpawnPoolWorker-4 - 7948 - 1
SpawnPoolWorker-3 - 10168 - 2
SpawnPoolWorker-1 - 4984 - 3
SpawnPoolWorker-5 - 5592 - 4
SpawnPoolWorker-2 - 11344 - 5
SpawnPoolWorker-4 - 7948 - 6
SpawnPoolWorker-3 - 10168 - 7
SpawnPoolWorker-1 - 4984 - 8
SpawnPoolWorker-5 - 5592 - 9
1、进程池同步执行任务:表示进程池中的进程在执行任务的时候一个执行完成另一个才能执行,如果没有执行完会等待上一个进程执行;
2、进程池异步执行任务:表示进程池中的进程同时执行任务,进程之间不会等待。
上述异步执行程序中如果将print("{1} - {0}".format(rest, i))改为print("{1} - {0}".format(rest.get(), i)),则异步执行效果与同步执行相同。
1、函数或方法被调用的时候,调用者是否得到最终的结果。直接得到最终结果,就是同步调用。不直接得到的最终的结果,就是异步调用。
2、同步:就是在发出一个功能调用时,在没有得到结果之前,该调用就不会返回,一旦调用返回,就得到返回值了。换句话说,就是由调用者主动等待这个调用结果。如进程、线程同步,可理解为进程或线程A和B一块配合,A执行到一定程度时要依靠B的某个结果,于是停下来,示意B运行;B依言执行,再将结果给A;A再继续操作
异步:调用在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说当一个异步功能调用发出后,调用者不能立刻得到结果。但是这个时候被调用者可以去执行下面的代码而不是一味的等待。
import threading
def use_thread():
"""打印线程名称"""
print("now threading name: {}".format(threading.current_thread().name))
"""使用线程实现"""
t = threading.Thread(target = loop, name = "loop_thread")
t.start()
t.join()
if __name__ == "__main__":
use_thread()
输出为:
now threading name: MainThread
now threading name: loop_thread
0
1
2
3
4
import threading
class LoopThread(threading.Thread):
"""自定义线程类"""
def run(self):
n = 0
while n < 5:
print("now threading name: {}".format(threading.current_thread().name))
print(n)
time.sleep(1)
n += 1
if __name__ == "__main__":
t1 = LoopThread(name = 'use_thread_oop')
t2 = LoopThread(name='use_thread_oop_2')
t1.start()
t2.start()
t1.join()
t2.join()
输出为:
now threading name: use_thread_oop
0
now threading name: use_thread_oop_2
0
now threading name: use_thread_oop_2
1
now threading name: use_thread_oop
1
now threading name: use_thread_oop_2
2
now threading name: use_thread_oop
2
now threading name: use_thread_oop_2
3
now threading name: use_thread_oop
3
now threading name: use_thread_oop_2
4
now threading name: use_thread_oop
4
import threading
import time
balance = 0
class BalanceThread(threading.Thread):
def __init__(self, n):
super().__init__()
self.n = n
def run(self):
global balance
print("original balance:{} thread_name:{}".format(balance, self.name))
# time.sleep(1)
for i in range(5):
try:
# my_lock.acquire()
# print(1)
# my_lock.acquire()
# print(2)
balance = balance + self.n
time.sleep(1)
balance = balance - self.n
time.sleep(1)
print("{}>>>>>>>>: {}".format(self.name, balance))
if __name__ == "__main__":
t1 = BalanceThread(5)
t2 = BalanceThread(8)
t1.start()
t2.start()
t1.join()
t2.join()
import threading
import time
balance = 0
my_lock = threading.Lock()
class BalanceThread(threading.Thread):
def __init__(self, n):
super().__init__()
self.n = n
def run(self):
global balance
print("original balance:{} thread_name:{}".format(balance, self.name))
# time.sleep(1)
for i in range(5):
try:
my_lock.acquire()
print(1)
# my_lock.acquire() LOCK命令如果加上此第二道锁,会产生死锁。资源已经被锁定,不能重复锁定
# print(2)
balance = balance + self.n
time.sleep(1)
balance = balance - self.n
time.sleep(1)
print("{}>>>>>>>>: {}".format(self.name, balance))
finally:
my_lock.release()
# my_lock.release()
if __name__ == "__main__":
t1 = BalanceThread(5)
t2 = BalanceThread(8)
t1.start()
t2.start()
t1.join()
t2.join()
输出为:
original balance:0 thread_name:Thread-1
1
original balance:5 thread_name:Thread-2
Thread-1>>>>>>>>: 0
1
Thread-1>>>>>>>>: 0
1
Thread-1>>>>>>>>: 0
1
Thread-1>>>>>>>>: 0
1
Thread-1>>>>>>>>: 0
1
Thread-2>>>>>>>>: 0
1
Thread-2>>>>>>>>: 0
1
Thread-2>>>>>>>>: 0
1
Thread-2>>>>>>>>: 0
1
Thread-2>>>>>>>>: 0
如果将第二道锁打开,输出为:
original balance:0 thread_name:Thread-1
1
original balance:0 thread_name:Thread-2
原因:资源已经被锁定,不能重复锁
import threading
import time
balance = 0
my_lock = threading.RLock()
class BalanceThread(threading.Thread):
def __init__(self, n):
super().__init__()
self.n = n
def run(self):
global balance
print("original balance:{} thread_name:{}".format(balance, self.name))
# time.sleep(1)
for i in range(5):
try:
my_lock.acquire()
print(1)
my_lock.acquire()
print(2)
balance = balance + self.n
time.sleep(1)
balance = balance - self.n
time.sleep(1)
print("{}>>>>>>>>: {}".format(self.name, balance))
finally:
my_lock.release()
my_lock.release()
if __name__ == "__main__":
t1 = BalanceThread(5)
t2 = BalanceThread(8)
t1.start()
t2.start()
t1.join()
t2.join()
输出为:
original balance:0 thread_name:Thread-1
1
2
original balance:5 thread_name:Thread-2
Thread-1>>>>>>>>: 0
1
2
Thread-1>>>>>>>>: 0
1
2
Thread-1>>>>>>>>: 0
1
2
Thread-2>>>>>>>>: 0
1
2
Thread-2>>>>>>>>: 0
1
2
Thread-2>>>>>>>>: 0
1
2
Thread-2>>>>>>>>: 0
1
2
Thread-2>>>>>>>>: 0
1
2
Thread-1>>>>>>>>: 0
1
2
Thread-1>>>>>>>>: 0
Lock和RLock适用with语法
import threading
import time
from concurrent.futures.thread import ThreadPoolExecutor
from multiprocessing.dummy import Pool
def run(n):
time.sleep(1)
print(threading.current_thread().name, n)
def main():
"""不是用线程"""
for n in range(5):
run(n)
def main_use_thread():
"""适用线程"""
ls = []
for count in range(10):
for i in range(10):
t = threading.Thread(target=run, args=(i,))
t.start()
ls.append(t)
for l in ls:
l.join()
def main_use_pool():
"""使用线程池优化"""
pool = Pool(10)
pool.map(run, range(100))
pool.close()
pool.join()
def main_use_executor():
"""适用ThreadPoolExecutor类实现线程池"""
with ThreadPoolExecutor(max_workers=10) as pool:
pool.map(run, range(100))
if __name__ == "__main__":
ts = time.time()
main()
print(time.time() - ts)
ts = time.time()
main_use_thread()
print(time.time() - ts)
ts = time.time()
main_use_pool()
print(time.time() - ts)
ts = time.time()
main_use_executor()
print(time.time() - ts)
ThreadPoolExecutor比multiprocessing.dummy.Pool效率略高。
def yield_test():
"""实现协程函数"""
while True:
n = yield
print(n)
if __name__ =="__main__":
g = yield_test() # g是一个生成器
next(g) # 程序运行到yield就停住了,等待下一个next
# g.send(None) # 没有给x赋值,执行print语句,打印出None,继续循环停在yield处,等同于next()
g.send(666) # 我们给yield发送值1,然后这个值被赋值给了x,并且打印出来,然后继续下一次循环停在yield处
g.send(888) # 同上next(g)
g.send(999) # 同上next(g)
输出为:
666
888
999
经典生产者消费者模型:
def consumer():
r = ''
while True:
n = yield r
if not n:
print("return")
return
print('[CONSUMER] Consuming %s...' % n)
r = '200 OK'
def produce(c):
# c.send(None)
next(c)
n = 0
while n < 2:
n = n + 1
print('[PRODUCER] Producing %s...' % n)
r = c.send(n)
print('[PRODUCER] Consumer return: %s' % r)
try:
# c.send(0)
c.send(False)
# c.send(None)
except StopIteration:
c.close()
print("close")
c = consumer()
produce(c)
输出为:
[PRODUCER] Producing 1…
[CONSUMER] Consuming 1…
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 2…
[CONSUMER] Consuming 2…
[PRODUCER] Consumer return: 200 OK
return
close
import asyncio
async def do_sth(x):
"""定义协程函数"""
print('等待中:{0}'.format(x))
await asyncio.sleep(x)
# 判断是否为协程函数
print(asyncio.iscoroutinefunction(do_sth))
coroutine1 = do_sth(5)
# 事件的循环队列
loop = asyncio.get_event_loop()
# 注册任务
task = loop.create_task(coroutine1)
print(task)
# 等待协程任务执行结束
loop.run_until_complete(task)
print(task)
输出为:
等待中:5
async def compute(x, y):
print("computing x + y")
await asyncio.sleep(1)
return x + y
async def get_num(x, y):
rest = await compute(x, y)
print(rest)
loop = asyncio.get_event_loop()
task = loop.create_task(get_num(1, 2))
loop.run_until_complete(task)
loop.close()
输出为:
computing x + y
3
# 1. 定义一个队列
# 2. 让两个协程来进行通信
# 3. 让其中一个协程往队列中写入数据
# 4. 让另一个协程从队列中删除数据
import asyncio
import random
async def add(store, name):
"""
写入数据到队列
:param store: 队列的对象
:return:
"""
for i in range(5):
# 往队列中添加数字
num = '{0} - {1}'.format(name, i)
await asyncio.sleep(random.randint(1, 5))
await store.put(i)
print('{2} add one ... {0}, size: {1}'.format(
num, store.qsize(), name))
async def reduce(store):
"""
从队列中删除数据
:param store:
:return:
"""
for i in range(10):
rest = await store.get()
print(' reduce one.. {0}, size: {1}'.format(rest, store.qsize()))
if __name__ == '__main__':
# 准备一个队列
store = asyncio.Queue(maxsize=5)
a1 = add(store, 'a1')
a2 = add(store, 'a2')
r1 = reduce(store)
# 添加到事件队列
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(a1, a2, r1))
loop.close()
输出为:
a1 add one … a1 - 0, size: 1
a2 add one … a2 - 0, size: 2
reduce one… 0, size: 1
reduce one… 0, size: 0
a2 add one … a2 - 1, size: 1
reduce one… 1, size: 0
a1 add one … a1 - 1, size: 1
reduce one… 1, size: 0
a1 add one … a1 - 2, size: 1
reduce one… 2, size: 0
a2 add one … a2 - 2, size: 1
reduce one… 2, size: 0
a1 add one … a1 - 3, size: 1
reduce one… 3, size: 0
a2 add one … a2 - 3, size: 1
reduce one… 3, size: 0
a1 add one … a1 - 4, size: 1
reduce one… 4, size: 0
a2 add one … a2 - 4, size: 1
reduce one… 4, size: 0
import random
from queue import Queue
import asyncio
class Bread(object):
""" 馒头类 """
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
async def consumer(name, basket, lock):
"""
消费者
:param name 协程的名称
:param basket 篮子,用于存放馒头
:return:
"""
while True:
async with lock:
# 如果没有馒头了,则自己休息,唤醒生产者进行生产
if basket.empty():
print('{0}@@@消费完了@@@'.format(name))
# 唤醒他人
lock.notify_all()
# 休息
await lock.wait()
else:
# 取出馒头
bread = basket.get()
print('>>{0} 消费馒头 {1}, size: {2}'.format(
name, bread, basket.qsize()
))
await asyncio.sleep(random.randint(1, 5))
async def producer(name, basket, lock):
"""
生产者
:param name 协程的名称
:param basket 篮子,用于存放馒头
:return:
"""
print('{0} 开始生产'.format(name))
while True:
async with lock:
# 馒头生产满了,休息生产者,唤醒消费者进行消费
if basket.full():
print('{0} 生产满了'.format(name))
# 唤醒他人
lock.notify_all()
# 自己休息
await lock.wait()
else:
# 馒头的名字
bread_name = '{0}_{1}'.format(name, basket.counter)
bread = Bread(bread_name)
# 将馒头放入篮子
basket.put(bread)
print('>>{0} 生产馒头 {1}, size: {2}'.format(name, bread_name, basket.qsize()))
# 计数+ 1
basket.counter += 1
await asyncio.sleep(random.randint(1, 2))
class Basket(Queue):
""" 自定义的仓库 """
# 馒头生产的计数器
counter = 0
def main():
lock = asyncio.Condition()
# 篮子,用于放馒头,协程通信使用
basket = Basket(maxsize=5)
p1 = producer('P1', basket, lock)
p2 = producer('P2', basket, lock)
p3 = producer('P3', basket, lock)
c1 = consumer('C1', basket, lock)
c2 = consumer('C2', basket, lock)
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(p1, p2, p3, c1, c2))
loop.close()
if __name__ == '__main__':
main()
输出为:
P1 开始生产
>>P1 生产馒头 P1_0, size: 1
P2 开始生产
P3 开始生产
>>P2 生产馒头 P2_1, size: 2
>>P3 生产馒头 P3_2, size: 3
>>C1 消费馒头 P1_0, size: 2
>>C2 消费馒头 P2_1, size: 1
>>P1 生产馒头 P1_3, size: 2
>>P2 生产馒头 P2_4, size: 3
>>P3 生产馒头 P3_5, size: 4
>>C1 消费馒头 P3_2, size: 3
>>C2 消费馒头 P1_3, size: 2
>>P1 生产馒头 P1_6, size: 3
>>P2 生产馒头 P2_7, size: 4
>>P3 生产馒头 P3_8, size: 5
>>C1 消费馒头 P2_4, size: 4
>>C2 消费馒头 P3_5, size: 3
>>P1 生产馒头 P1_9, size: 4
>>P2 生产馒头 P2_10, size: 5
P3 生产满了
>>C1 消费馒头 P1_6, size: 4
>>C2 消费馒头 P2_7, size: 3
>>P1 生产馒头 P1_11, size: 4
>>P2 生产馒头 P2_12, size: 5
>>C1 消费馒头 P3_8, size: 4
>>C2 消费馒头 P1_9, size: 3
>>P1 生产馒头 P1_13, size: 4
协程理解参考链接:
廖雪峰的官方网站
网名还没想好