Python__模块(TIME-进程/线程)__concurrent / multiprocessing

本文详细介绍了并发编程中的线程和进程概念,包括它们的区别、异步与同步操作,以及concurrent.futures模块中提供的ThreadPoolExecutor和ProcessPoolExecutor的使用。同时探讨了multiprocessing模块的进程创建、通信与同步机制,如Process、Queue和Lock等组件的应用。

concurrent(简介)

进程或线程的使用。


concurrent(了解)

【线程进程区别】

  • 线程是共享内存空间。

  • 进程是内存独立状态。

同一个进程的线程之间可以直接交流。

两个进程想通信,必须通过一个中间代理来实现。

使用多线程能充分利用 CPU 来提供程序的执行效率。

每一个进程启动时都会最先产生一个线程,即主线程,然后主线程会再创建其他的子线程。

一个进程可包含多个线程。

【同步异步】

同步

提交了一个任务,必须等任务执行完了(拿到返回值),才能执行下一行代码。

相当于执行任务的串行执行。

异步

交了一个任务,无需等执行完,可以直接执行下一行代码。


concurrent(参数列表)

concurrent.futures

模块提供了高度封装的异步调用接口。

ThreadPoolExecutor

线程池,提供异步调用

ProcessPoolExecutor

进程池,提供异步调用

subprocess

子进程操作

result(timeout=None)

取得结果

add_done_callback(fn)

回调函数

submit(fn, *args, **kwargs)

异步提交任务

wait=True

等待池内所有任务执行完毕回收完资源后才继续

wait=False

立即返回,并不会等待池内的任务执行完毕,

但不管wait参数为何值,整个程序都会等到所有任务执行完毕

shutdown(wait=True)

相当于进程池的pool.close()+pool.join()操作

map(func, *iterables, timeout=None, chunksize=1)

取代for循环submit的操作。


concurrent(参考代码)

简单的多线程操作

from concurrent.futures import ThreadPoolExecutor
import time

def task(i):
    print(f"在执行任务{i}")
    print("假设这是一个URL请求的地址....")
    time.sleep(5)

pool = ThreadPoolExecutor(2)  # 4个线程
for i in range(20):
    pool.submit(task, i)

上一个例子的简化版(map)


# 例子-map用法
from concurrent.futures import ThreadPoolExecutor
from threading import Thread, currentThread
import time

def task(i):
    print(f"{currentThread().name} 在执行任务{i}")
    time.sleep(1)

if __name__ == "__main__":
    pool = ThreadPoolExecutor(4)
    pool.map(task, range(0, 20))  # map取代了for+submit

multiprocessing(简介)

进程的进阶用法。


multiprocessing(了解)

multiprocessing-模块用来开启子进程。

功能:支持子进程,通信和共享数据,执行不同执行的同步。

提供->Process,Queue,Pipe,Lock等组件。


multiprocessing(参数列表)

Process类

由该类实例化得到的对象,可用来开启一个子进程。

【语法】 Process([group [, target [, name [, args [, kwargs]]]]])

group  (暂时忽略) 参数未使用,值始终为None。

target (函数) 表示调用对象,即子进程要执行的任务。

args   (函数的参数) 表示调用对象的位置参数元组,args=(1,2,'mike')。

kwargs (暂时忽略) 表示调用对象的字典,kwargs={'name':'mike','age':'18'}。

常用函数

start()

(启动进程)调用该子进程中的run()

run()

(进程启动时运行的方法)正是它去调用target指定的函数。

terminate()

(强制终止进程),不会进行任何清理操作,如果创建了子进程,

该子进程就成了僵尸进程,使用该方法需要特别小心这种情况,

如果还保存了一个锁那么也将不会被释放,进而导致死锁。

is_alive()

进程仍然运行,返回True。

join([timeout])

主进程等待终止(主进程处于等的状态)

daemon

默认值为False,如果设为True,代表子进程为后台运行的守护进程,

父进程终止时,子进程也随之终止,并且设定为True后。

name

进程的名称

pid

进程的pid


multiprocessing(参考代码)

单进程

import multiprocessing
import time

def func(msg):
    for i in range(20):
        print(msg, i)
        time.sleep(1)

if __name__ == "__main__":
    p = multiprocessing.Process(target=func, args=("input content....",))
    p.start()
    p.join()

    print("Sub-process done.")

多进程

import multiprocessing
import time

def fc1(msg):
    for i in range(3):
        print("{}:黄岛主 正在进行任务{}....".format(msg, i + 1))
        time.sleep(1)
    print(">>>>>> {}大佬 任务完成".format(msg))


def fc2(msg):
    for i in range(2):
        print("{}:欧阳锋 正在进行任务{}....".format(msg, i + 1))
        time.sleep(1)
    print(">>>>>> {}大佬 任务完成".format(msg))


def fc3(msg):
    for i in range(5):
        print("{}:段大师 正在进行任务{}....".format(msg, i + 1))
        time.sleep(1)
    print(">>>>>> {}大佬 任务完成".format(msg))


def fc4(msg):
    for i in range(2):
        print("{}:洪七公 正在进行任务{}....".format(msg, i + 1))
        time.sleep(1)
    print(">>>>>> {}大佬 任务完成".format(msg))


if __name__ == "__main__":
    pool = multiprocessing.Pool(processes=4)  # CPU核数
    result = []
    person = ["东邪", "西毒", "南帝", "北丐"]
    result.append(pool.apply_async(fc1, (person[0],)))
    result.append(pool.apply_async(fc2, (person[1],)))
    result.append(pool.apply_async(fc3, (person[2],)))
    result.append(pool.apply_async(fc4, (person[3],)))
    pool.close()
    pool.join()
    print("全部OK....")

多线程队列

import multiprocessing as mp

def job(x):
    res = 0
    for i in range(4):
        res += i
    x.put(res)

if __name__ == "__main__":
    # 定义一个多线程队列,用来存储结果
    q = mp.Queue()
    # 定义两个线程函数,用来处理同一个任务
    # Process / Thread
    p1 = mp.Process(target=job, args=(q,))
    p2 = mp.Process(target=job, args=(q,))
    # 分别启动、连接两个线程
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    fc1 = q.get()
    fc2 = q.get()
    print(fc1 + fc2)

进程锁

# 防止不同进程之间抢占共享资源
import multiprocessing as mp
import time

def job(v, num, l):
    l.acquire()  # 锁住
    for _ in range(5):
        time.sleep(1)
        v.value += num  # 获取共享内存
        print("value=", v.value)
    l.release()  # 释放

def multicore():
    lock = mp.Lock()  # 定义一个进程锁
    value = mp.Value("i", 20)  # 定义共享内存
    p1 = mp.Process(target=job, args=(value, 1, lock))  # 需要将lock传入
    p2 = mp.Process(target=job, args=(value, 3, lock))
    p1.start()
    p2.start()
    p1.join()
    p2.join()

if __name__ == "__main__":
    multicore()

NFO: 192.168.23.139:43876 - "POST /token HTTP/1.1" 500 Internal Server Error ERROR: Exception in ASGI application Traceback (most recent call last): File "/usr/local/lib/python3.10/site-packages/fastapi/concurrency.py", line 27, in contextmanager_in_threadpool yield await run_in_threadpool(cm.__enter__) File "/usr/local/lib/python3.10/site-packages/starlette/concurrency.py", line 37, in run_in_threadpool return await anyio.to_thread.run_sync(func) File "/usr/local/lib/python3.10/site-packages/anyio/to_thread.py", line 56, in run_sync return await get_async_backend().run_sync_in_worker_thread( File "/usr/local/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 2147, in run_sync_in_worker_thread worker.start() File "/usr/local/lib/python3.10/threading.py", line 935, in start _start_new_thread(self._bootstrap, ()) RuntimeError: can't start new thread During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/local/lib/python3.10/site-packages/uvicorn/protocols/http/h11_impl.py", line 396, in run_asgi result = await app( # type: ignore[func-returns-value] File "/usr/local/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 70, in __call__ return await self.app(scope, receive, send) File "/usr/local/lib/python3.10/site-packages/fastapi/applications.py", line 1054, in __call__ await super().__call__(scope, receive, send) File "/usr/local/lib/python3.10/site-packages/starlette/applications.py", line 112, in __call__ await self.middleware_stack(scope, receive, send) File "/usr/local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 187, in __call__ raise exc File "/usr/local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 165, in __call__ await self.app(scope, receive, _send) File "/usr/local/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 62, in __call__ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app raise exc File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app await app(scope, receive, sender) File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 714, in __call__ await self.middleware_stack(scope, receive, send) File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 734, in app await route.handle(scope, receive, send) File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 288, in handle await self.app(scope, receive, send) File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 76, in app await wrap_app_handling_exceptions(app, request)(scope, receive, send) File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app raise exc File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app await app(scope, receive, sender) File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 73, in app response = await f(request) File "/usr/local/lib/python3.10/site-packages/fastapi/routing.py", line 291, in app solved_result = await solve_dependencies( File "/usr/local/lib/python3.10/site-packages/fastapi/dependencies/utils.py", line 634, in solve_dependencies solved = await solve_generator( File "/usr/local/lib/python3.10/site-packages/fastapi/dependencies/utils.py", line 560, in solve_generator return await stack.enter_async_context(cm) File "/usr/local/lib/python3.10/contextlib.py", line 619, in enter_async_context result = await _cm_type.__aenter__(cm) File "/usr/local/lib/python3.10/contextlib.py", line 199, in __aenter__ return await anext(self.gen) File "/usr/local/lib/python3.10/site-packages/fastapi/concurrency.py", line 30, in contextmanager_in_threadpool await anyio.to_thread.run_sync( File "/usr/local/lib/python3.10/site-packages/anyio/to_thread.py", line 56, in run_sync return await get_async_backend().run_sync_in_worker_thread( File "/usr/local/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 2147, in run_sync_in_worker_thread worker.start() File "/usr/local/lib/python3.10/threading.py", line 935, in start _start_new_thread(self._bootstrap, ()) RuntimeError: can't start new thread INFO: 192.168.48.1:33210 - "GET /users/me HTTP/1.0" 500 Internal Server Error ERROR: Exception in ASGI application Traceback (most recent call last): File "/usr/local/lib/python3.10/site-packages/uvicorn/protocols/http/h11_impl.py", line 396, in run_asgi result = await app( # type: ignore[func-returns-value] File "/usr/local/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 70, in __call__ return await self.app(scope, receive, send) File "/usr/local/lib/python3.10/site-packages/fastapi/applications.py", line 1054, in __call__ await super().__call__(scope, receive, send) File "/usr/local/lib/python3.10/site-packages/starlette/applications.py", line 112, in __call__ await self.middleware_stack(scope, receive, send) File "/usr/local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 187, in __call__ raise exc File "/usr/local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 165, in __call__ await self.app(scope, receive, _send) File "/usr/local/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 62, in __call__ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app raise exc File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app await app(scope, receive, sender) File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 714, in __call__ await self.middleware_stack(scope, receive, send) File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 734, in app await route.handle(scope, receive, send) File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 288, in handle await self.app(scope, receive, send) File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 76, in app await wrap_app_handling_exceptions(app, request)(scope, receive, send) File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app raise exc File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app await app(scope, receive, sender) File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 73, in app response = await f(request) File "/usr/local/lib/python3.10/site-packages/fastapi/routing.py", line 291, in app solved_result = await solve_dependencies( File "/usr/local/lib/python3.10/site-packages/fastapi/dependencies/utils.py", line 640, in solve_dependencies solved = await run_in_threadpool(call, **solved_result.values) File "/usr/local/lib/python3.10/site-packages/starlette/concurrency.py", line 37, in run_in_threadpool return await anyio.to_thread.run_sync(func) File "/usr/local/lib/python3.10/site-packages/anyio/to_thread.py", line 56, in run_sync return await get_async_backend().run_sync_in_worker_thread( File "/usr/local/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 2147, in run_sync_in_worker_thread worker.start() File "/usr/local/lib/python3.10/threading.py", line 935, in start _start_new_thread(self._bootstrap, ()) RuntimeError: can't start new thread
07-19
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

vip飞梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值