python并发编程

python并发编程

术语介绍

1. 进程、线程、协程
	进程: 
		计算机中资源分配和调度的最小工作单元(一个运行程序) 
		一个进程可以存在多个线程 进程间数据不共享
		进程状态-创建、就绪、运行、阻塞、退出
		进程间调度通过上下文(CPU寄存器中的值、进程状态、堆栈中的数据)切换
		应用于CPU密集型计算的业务(大量复杂运算等)
		操作系统内核控制分配
	线程: 
		计算机中的程序执行中的最小执行单元
        同个进程中多个线程共享数据
        线程间调度切换快于进程
        应用于IO密集型的业务(文件读写、网络IO) 
    协程:
    	微线程 协程调度由程序业务层控制切换 
    	没有线程上下文切换的资源开销
    	应用于IO密集型的业务或CPU密集型计算(进程+协程模式)
        
2. 并发、并行、串行
	并发:
		依次执行 
		某个时间段存在多个任务执行
		某个时刻有且仅有一个任务在执行
        在同一个CPU上执行
	并行:
		同时执行
		在多个CPU上执行(多核CPU、单核会保持进程切换调度于多核运行模式一致)
	串行:
		依次顺序执行
		需等待上个任务执行完毕再执行下个任务
		
3. 同步、异步、互斥
	同步:
		串行 依次有顺序执行 需要等待上个任务完成才执行下个任务
	异步:
		并发、并行 多个任务同时在一个时间段同时执行 无需等待其他任务完成 各自执行对应的任务
	互斥:
		保证某个时间段有且仅有一个任务在处理(共享)资源
		
4. 进程p、线程t 同步和通信相关支持
	Lock(RLock): p t
	Event: p t
	Condition: p t
	Semaphore: p t
	Queue: p t
	Pipe: p


进(线)程

线程创建

'''
python并发编程
'''
import os
import random
import time
from threading import Thread


def task(task_name):
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-任务执行...")
    time.sleep(random.randrange(1, 3))
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-任务结束...")

    
def thread_create_v1():
    """
    线程创建方式1
    from threading import Thread
    :return:
    """
    for i in range(2):
        Thread(target=task, args=(f"t{i}",)).start()
        
    
class MyThread(Thread):
    def __init__(self, task_name):
        super().__init__()
        self.name = task_name

    def run(self) -> None:
        """
        任务处理业务流程
        :return:
        """
        task(task_name=self.name)
        
        
def thread_create_v2():
    """
    创建线程方式2
    继承Thread并实现run方法
    :return:
    """
    for i in range(2):
        MyThread(f"mt{i}").start()
       

if __name__ == '__main__':
    thread_create_v2()
    print(f"{os.getpid()}-{os.getppid()}-程序结束...")

image


进程创建

import os
import random
import time
from multiprocessing import Process


def task(task_name):
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-任务执行...")
    time.sleep(random.randrange(1, 3))
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-任务结束...")


def process_create_v1():
    """
    进程创建方式1
    from multiprocessing import Process
    :return:
    """

    '''
       Process.__init__(
       group=None,
       target=None,
       name=None,
       args=(),
       kwargs={},
       *,
       daemon=None)
    '''
    p1 = Process(target=task, args=("a",))
    p2 = Process(target=task, args=("b",))
    p1.start()  # 任务执行开始
    # print(f"进程id={p1.pid};进程名={p1.name}-进程是否在运行={p1.is_alive()}")
    # p1.terminate()  # 需要放到start后 则会直接终止任务执行
    p2.start()
    p1.join()  # 等待任务执行完毕(可设置超时时间timeout)
    p2.join()


class MyProcess(Process):
    def __init__(self, task_name):
        super().__init__()
        self.name = task_name

    def run(self) -> None:
        """
        任务处理业务流程
        :return:
        """
        task(task_name=self.name)


def process_create_v2():
    """
    进程创建方式2
    from multiprocessing import Process
    继承Process父类并重写run方法
    :return:
    """
    p1 = MyProcess("a")
    p2 = MyProcess("b")
    p1.start()
    p2.start()
    p1.join()
    p2.join()


def process_daemon_true():
    """
    守护进程
    主进程结束会终止未等待执行的守护进程
    :return:
    """
    # p = Process(target=task, args=("c", ), daemon=True)
    p1 = Process(target=task, args=("c", ))
    p2 = Process(target=task, args=("d", ))
    p1.daemon = True  # 设置为守护进程
    p1.start()
    p2.start()
    # p2.join()  // 若不等待则主进程结束 守护进程会直接被终止执行


if __name__ == '__main__':
    process_create_v1()
    print("="*30)
    process_create_v2()
    print("=" * 30)
    process_daemon_true()
    print(f"{os.getpid()}-{os.getppid()}-程序结束...")

image


进(线)程通信

互斥锁Lock

import os
import time
from multiprocessing import Process, Lock


def task_lock(task_name, lock=None):
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-任务执行...")
    if not lock:
        time.sleep(random.randrange(1, 3))
        print(f"{task_name}-{os.getpid()}-{os.getppid()}-任务结束...")
    else:
        with lock:
            time.sleep(random.randrange(1, 3))
            print(f"{task_name}-{os.getpid()}-{os.getppid()}-任务结束...")
        
        
def process_lock():
    """
    Lock: 加锁 整体任务业务加锁<=>Process().join()   对一个进程(线程)可一次加锁
    RLock: 递归锁 对一个进程(线程)可多次加锁 同一进程(线程)可多次获取锁 获取多少次就需要释放多少次
    :return:
    """
    lock = Lock()
    # 加锁
    for i in range(2):
        Process(target=task_lock, args=(i, lock)).start()

    # 未加锁
    for i in range(3, 5):
        Process(target=task_lock, args=(f">>>{i}", )).start()
        

if __name__ == '__main__':
    process_lock()
    print(f"{os.getpid()}-{os.getppid()}-程序结束...")

image


事件Event

import os
import random
import time
from multiprocessing import Process, Event


def event_task(task_name, evt):
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-任务执行...")
    evt.wait()  # 阻塞进程执行 直到调用evt.set() <=> Event的标识为True(evt.is_set()=True)则会唤醒所有等待该Event对象的进程
    print(f"{task_name}-event_task-evt.is_set()=", evt.is_set())
    # evt.clear()  # event事件重置为False 会导致使用该Event事件的进程一直阻塞
    time.sleep(random.randrange(1, 3))
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-任务结束...")


def process_event():
    """
    Event对象事件(最好单次使用 若一个进程需要多次使用建议用Condition对象替代)
    from multiprocessing import Event
    多进程间通信: 通过Event事件控制进程间执行流程、监听进程状态
    Event.wait(): 阻塞所有等待Event对象的进程 直到调用Event.set()且Event.is_set()为True时 会被唤醒
    Event.set(): 设置Event.is_set()为True 唤醒所有等待Event对象阻塞的进程
    Event.is_set(): 事件标识 True:唤醒执行 False:阻塞等待
    Event.clear(): 重置Event对象事件为False
    :return:
    """
    evt = Event()
    p1 = Process(target=event_task, args=("e", evt))
    p2 = Process(target=event_task, args=("f", evt))
    p1.start()
    p2.start()
    print("process_event-evt.is_set()=", evt.is_set())
    evt.set()  # 唤醒所有等待Event对象的阻塞进程


    
if __name__ == '__main__':
    process_event()
    print(f"{os.getpid()}-{os.getppid()}-程序结束...")

image


条件变量Condition

'''
python并发编程
'''
import os
import random
import time
from multiprocessing import Process, Condition


def condition_task(task_name, cond, flag):
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-flag({flag})-任务执行...")
    count = 0
    with cond:
        while 1:
            if flag >= 1:  # 第一层条件控制
                while 1:
                    if count < 3:
                        time.sleep(2)
                        count += 1
                    else:
                        break
                    print(f"flag={flag};count={count}")
                if flag >= 1 and count < 3:  # 第二层条件控制
                    cond.wait()  # 阻塞当前进程(线程)
                else:
                    cond.notify()   # 唤醒当前等待进程(线程)
                    # cond.notify_all()  # 唤醒所有等待进程(线程)
                    break
            else:
                break
        print(f"{task_name}-{os.getpid()}-{os.getppid()}-flag({flag})-任务结束...")


def process_condition():
    """
    condition条件变量(synchronize.Condition)
    进程间通信: 通过condition条件变量控制进程间执行流程、监听进程状态
    from multiprocessing import Condition

    Condition.acquire():获取锁
    Condition.release():释放锁
    Condition.wait(timeout=None): 释放锁并阻塞当前进程(调用该方法前先获取锁否则会抛出RuntimeError)直到超时或直到其它进程相同Condition对象调用了notify|notify_all方法被唤醒 之后当前进程会重新尝试获取锁并在成功获取锁返回True 若超时则返回False
    Condition.wait_for(predicate, timeout=None): 阻塞当前进程直到超时返回False或者直到条件变量Condition(predicate)返回True
    Condition.notify(n=1): 唤醒等待该Condition条件变量的一个或n个进程(调用该方法需要优先获取锁且被唤醒的进程不会马上从wait()返回唤醒 直到重新获取到锁 notify不会释放锁 需要进程本身调用wait或release释放)
    Condition.notify_all(): 唤醒等待该Condition对象的所有线程
    :return:
    """
    cond = Condition()
    for i in range(3):
        Process(target=condition_task, args=(f"c-{i}", cond, i)).start()
      

if __name__ == '__main__':
    process_condition()
    print(f"{os.getpid()}-{os.getppid()}-程序结束...")

image


信号量Semaphore

import os
import random
import time
from multiprocessing import Process, Semaphore


def task_semaphore(task_name, sema):
    sema.acquire()
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-{sema.get_value()}-任务执行...")
    time.sleep(random.randrange(1, 3))
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-{sema.get_value()}-任务结束...")
    sema.release()
    # with sema:
    #     print(f"{task_name}-{os.getpid()}-{os.getppid()}-{sema.get_value()}-任务执行...")
    #     time.sleep(random.randrange(1, 3))
    #     print(f"{task_name}-{os.getpid()}-{os.getppid()}-{sema.get_value()}-任务结束...")
        
        
def process_semaphore(n=1):
    """
    Semaphore信号量:
    Semaphore(1)<=>互斥锁<=>串行
    Semaphore(n:int)可同时允许n个数量的进程(线程)执行
    Semaphore.acquire():  Semaphore信号量大于0则Semaphore信号量-1 反之异常  加锁阻塞
    Semaphore.release():  Semaphore信号量+1  释放锁唤醒 
    :return:
    """
    sema = Semaphore(n)  # n决定同时执行的进程(线程)数 同时也决定达到该信号量值后续任务均需要等待
    for i in range(n+1):
        Process(target=task_semaphore, args=(f"s{i}", sema)).start()
    
    
if __name__ == '__main__':
    process_semaphore(n=2)
    print(f"{os.getpid()}-{os.getppid()}-程序结束...")

image


队列Queue

import os
import random
import time

        
def task_queue(task_name, q, flag):
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-{q.qsize()}-任务执行...")
    if flag == 'in':  # 2种工作模式
        for i in range(3):
            if not q.full():
                q.put(f"data{i}",)  # 生产(写)数据
                print(f"{task_name}-写入数据({q.qsize()}):data{i}")
    elif flag == 'out':
        while 1:
            if not q.empty():
                data = q.get()  # 消费(读)数据
                print(f"{task_name}-读取数据({q.qsize()}):{data}")
            else:
                break
    else:
        return
    time.sleep(random.randrange(1, 3))
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-{q.qsize()}-任务结束...")
    
    
def process_queue():
    """
    from multiprocessing import Queue
        JoinableQueue、SimpleQueue(<=>locked pipe)
        put: 发送消息
        get: 接收消息
        qsize: 队列大小
        empty: 队列是否为空
        full: 队列是否已满
    :return:
    """
    from multiprocessing import Process, Queue
    q = Queue()  # maxsize 可设置队列最大值
    Process(target=task_queue, args=("in", q, "in")).start()
    for i in range(2):
        Process(target=task_queue, args=(f"out{i}", q, "out")).start()


def task_tqueue(task_name, q, flag):
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-{q.qsize()}-任务执行...")
    if flag == 'in':  # 2种工作模式
        for i in range(3):
            if not q.full():
                q.put(f"data{i}",)  # 生产(写)数据
                print(f"{task_name}-写入数据({q.qsize()}):data{i}")
    elif flag == 'out':
        while 1:
            if not q.empty():
                data = q.get()  # 消费(读)数据
                q.task_done()
                print(f"{task_name}-读取数据({q.qsize()}):{data}")
            else:
                break
    else:
        return
    time.sleep(random.randrange(1, 3))
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-{q.qsize()}-任务结束...")
    
    
def thread_queue():
    """
    from queue import Queue(只支持线程 进程会有问题)
        Queue,LifoQueue,PriorityQueue,SimpleQueue(fifo)
        Queue.task_done(): 标识任务为完成 线程任务每次调用get建议加上该方法
        Queue.join(): 阻塞所有任务 直到所有未完成的任务标识降为0
        Queue.qsize(): 队列大小
        Queue.empty(): 队列是否为空
        Queue.full(): 队列是否已满
        Queue.put(): 写数据  可设置block是否阻塞写  timeout超时时间
        Queue.get(): 读数据 可设置block是否阻塞读  timeout超时时间
    :return:
    """
    from queue import Queue as Q
    from threading import Thread
    q = Q()  # maxsize 可设置队列最大值
    Thread(target=task_tqueue, args=("in", q, "in")).start()
    for i in range(2):
        Thread(target=task_tqueue, args=(f"out{i}", q, "out")).start()
    
    
if __name__ == '__main__':
    # process_queue()
    thread_queue()
    print(f"{os.getpid()}-{os.getppid()}-程序结束...")

image


管道Pipe

import os
import random
import time
from multiprocessing import Process, Pipe

def task_pipe(task_name, p, flag):
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-{flag}-任务执行...")
    if flag == "in":  # 可写
        for i in range(5):
            p.send(i)
            print(f"{task_name}-发送消息:{i}")
        p.close()
    elif flag == "out":  # 可读
        while 1:
            try:
                data = p.recv()
                print(f"{task_name}-接收消息:{data}")
            except EOFError:
                p.close()
                break
    else:
        p.close()
        return
    time.sleep(random.randrange(1, 3))
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-{flag}-任务结束...")


def process_pipe():
    """
    Pipe管道:
        多进程间的数据交互
    from multiprocessing import Pipe
    Pipe.send(): 发送数据
    Pipe.send_bytes(buf,offset=0,size=None): 从特定偏移量offset发送特定字节大小size的数据
    Pipe.recv(): 接收数据
    Pipe.recv_bytes(maxlength=None): 接收特定长度字节的数据
    Pipe.poll(): 轮询是否有可读的连接通道
    Pipe.close(): 关闭连接通道
    :return:
    """
    p = Pipe(duplex=False)  # 返回元组(con1, con2)  参数duplex=True 可读可写-默认True
    # c1, c2 = p
    # print(p, type(p))
    # """
    # duplex=False
    # out:
    # c1: True False  只可读
    # c2: False True  只可写
    # """
    # print("c1:", c1.readable, c1.writable)
    # print("c2:", c2.readable, c2.writable)
    rp, wp = p
    Process(target=task_pipe, args=("wp", wp, "in")).start()
    Process(target=task_pipe, args=("rp", rp, "out")).start()
    
    
if __name__ == '__main__':
    process_pipe()
    print(f"{os.getpid()}-{os.getppid()}-程序结束...")

image


进(线)程池

import os
import random
import time
from multiprocessing import Process



def task_process_pool(task_name, n):
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-任务执行...")
    time.sleep(random.randrange(1, 3))
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-任务结束...")
    return n * 2
    
    
def process_pool():
    """
    进程池Pool
    from multiprocessing import Pool
    Pool.apply(): 同步阻塞直到获取结果 任务函数入参元组  结果无序
    Pool.apply_async(): 异步非阻塞 可携带参数正常回到函数和异常回到函数 正常返回则回调正常回调函数 反之回调异常回调函数  结果无序
    Pool.map(): 同步阻塞直到获取结果  任务函数入参可迭代对象  结果有序
    Pool.map_async():异步非阻塞 可携带参数正常回到函数和异常回到函数  结果有序
    Pool.starmap_async(): 异步非阻塞  结果有序 针对任务函数传递多个参数 使用该方法
    Pool.close(): 关闭连接池 会等到任务执行完成
    Pool.terminate(): 停止连接池中的任务 无论是否已完成任务
    Pool.join(): 等待连接池中的任务完成
    
    线程池Pool
    from multiprocessing.pool import ThreadPool as tp
    或者
    from multiprocessing.dummy import Pool as tp
    以下是源码且ThreadPool继承Pool 相关方法一样
    def Pool(processes=None, initializer=None, initargs=()):
        from ..pool import ThreadPool
        return ThreadPool(processes, initializer, initargs)
    
    :return:
    """
    from multiprocessing import Pool
    
    p = Pool()
    for i in range(3):
        p.apply_async(task_process_pool,
                      args=(f"p{i}", i),
                      callback=lambda x: print(f"{x}"),
                      error_callback=lambda x: print(f"error={x}"))
    
        # res = p.apply_async(task_process_pool,
        #               args=(f"p{i}", i),
        #               callback=lambda x: print(f"{x}"),
        #               error_callback=lambda x: print(f"error={x}"))
        # print(res.get(), res.ready(), res.successful())
    
        # res = p.apply(task_process_pool,
        #               args=(f"p{i}", i))
        # print(res)  # 结果
        pass
    
    # p.starmap_async(task_process_pool,
    #                 ((f"p{i}", i) for i in range(3)),
    #                 callback=lambda x: print(f"{x}"),
    #                 error_callback=lambda x: print(f"error={x}")
    #                 )
    """
    out: [0,2,4] 结果集
    """
    p.close()
    p.join()
    pass

    
if __name__ == '__main__':
    process_pool()
    print(f"{os.getpid()}-{os.getppid()}-程序结束...")

image


并发池

import os
import random
import time


def task_pool(task_name, n):
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-任务执行...")
    time.sleep(random.randrange(1, 3))
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-任务结束...")
    return n * 2


def my_pool_executor():
    """
    并发池ThreadPoolExecutor| ProcessPoolExecutor(方法类似)
    submit():返回一个Future对象  有序结果
    map():  返回一个迭代器  有序结果
    shutdown(): wait=True 等待返回结果Future返回结束
    :return:
    """
    from concurrent.futures import ThreadPoolExecutor
    
    # 方式1
    with ThreadPoolExecutor(max_workers=3) as te:
        res_li = te.map(lambda x: task_pool(*x), ((f"p{i}", i) for i in range(3)))
        # print(type(res_li), res_li)  # 迭代器对象
        for rs in res_li:
            print("return_res=", rs)
    # 方式2        
    # with ThreadPoolExecutor(max_workers=3) as te:
    #     for i in range(3):
    #         res = te.submit(lambda x: task_pool(*x), (f"p{i}", i))
    #         # res = te.submit(lambda x: task_pool(*x), (f"p{i}", i)).add_done_callback(lambda futureX: futureX)
    #         # from concurrent.futures import Future
    #         # print(type(res), res)  # Future对象
    #         print("return_res=", res.result())  # 可设置超时时间
        
    
if __name__ == '__main__':
    my_pool_executor()
    print(f"{os.getpid()}-{os.getppid()}-程序结束...")

image



协程

send+yield

def task_yield():
    n = 1
    while n <= 3:
        d = yield n  # 暂停并获取值
        if not d:
            return
        print("recv<<<", d)
        n += 1


def task_send(g):
    g.send(None)  # <=>g.__next__() 唤醒或启动生成器g
    n = 1
    while n <= 3:
        try:
            print("send>>>", n)
            r = g.send(n)  # 发送值给yield表达式
            print("send(nextVal)>>>", r)
        except StopIteration:
            return
        n += 1


def send_and_yield():
    """
    send + yield 协程
    模拟任务切换执行
    :return:
    """
    g = task_yield()
    task_send(g)


if __name__ == '__main__':
    send_and_yield()
    print(f"{os.getpid()}-{os.getppid()}-程序结束...")

image


@asyncio.coroutine+yield from

@asyncio.coroutine
def task_asyncio(task_name):
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-任务执行...")
    yield from asyncio.sleep(1)  # 切换到其他任务执行
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-任务结束...")


def asyncio_loop():
    """
    @asyncio.coroutine + yield from 模拟协程任务交替执行
    @asyncio.coroutine装饰的函数称为协程
    yield from 用于将一个生成器部分操作指派给另一个生成器
    eg: a()是生成器(asyncio.Future()对象)
    def t():
        yield from a()
    :return:
    """
    print("是否是协程对象=", asyncio.iscoroutine(task_asyncio("a")))
    print("是否是协程函数=", asyncio.iscoroutinefunction(task_asyncio))
    lp = asyncio.get_event_loop()  # 创建一个事件循环
    lp.run_until_complete(asyncio.wait([task_asyncio("in"), task_asyncio("out")]))  # 执行协程任务直到完成
    lp.close()  # 关闭事件循环


if __name__ == '__main__':
    asyncio_loop()
    print(f"{os.getpid()}-{os.getppid()}-程序结束...")

image


async+await

import asyncio


async def async_task_1(af):
    """
    协程任务1
    :return:
    """

    print("开始写作业...")
    await asyncio.sleep(1)
    print(f"写作业中...")
    await asyncio.sleep(1)
    print(f"写作业中...")
    af.set_result(True)  # 设置值
    print("结束写作业...")
    # 获取结果时用到
    return "作业写完了"


async def async_task_2(af):
    """
    协程任务2
    :return:
    """
    print(f"未到时间睡觉...")
    # n = await af
    await asyncio.sleep(1)
    print(f"想睡觉...")
    # n = await af
    await asyncio.sleep(1)
    print(f"想睡觉...")
    # n = await af  # 获取值
    await asyncio.sleep(1)
    print(f"到点睡觉...")
    return "睡觉了"


async def run(af):
    f1, f2 = async_task_1(af), async_task_2(af)
    # await asyncio.gather(f1, f2)  # 方式1
    task_li = [f1, f2]
    rsl = await asyncio.gather(*task_li)  # 方式2
    # print("rsl=", rsl)  # rsl= ['作业写完了', '睡觉了']
    # done, no_done = await asyncio.wait(task_li)  # 方式3
    # for r in done:
    #     print("res=", r.result())


def async_await():
    """
    @asyncio.coroutine <=>async
    yield from <=> await

    async 修饰的函数为异步函数 :
        async def a():
            pass
    异步函数的实例化对象a()即为一个asyncio.Future() 协程对象
    python3.7:
        asyncio.ensure_future(a())
        <=>
        loop = asyncio.get_event_loop()
        loop.create_task(a())
        <=>
        asyncio.create_task(a())
    res = asyncio.gather(): 返回结果有序
    a, b = asyncio.wait([a(), b()]): 返回结果无序
    :return:
    """
    af = asyncio.Future()  # 新建一个Future()对象

    # 方式1
    # lp = asyncio.get_event_loop()
    # # lp.run_until_complete(run(af))
    # lp.run_until_complete(asyncio.wait([async_task_1(af), async_task_2(af)]))
    # lp.close()

    # 方式2
    # asyncio.run(asyncio.wait([async_task_1(af), async_task_2(af)]))
    asyncio.run(run(af))


if __name__ == '__main__':
    async_await()
    print(f"{os.getpid()}-{os.getppid()}-程序结束...")

image


gevent

pip install gevent
def task_gevent(task_name, n):
    """
    gevent任务
    :return:
    """
    import gevent,random,os
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-{gevent.getcurrent()}-任务执行...")
    gevent.sleep(random.randrange(1, 3))  # 模拟耗时
    print(f"{task_name}-{os.getpid()}-{os.getppid()}-{gevent.getcurrent()}-任务结束...")
    return n * 2


def gevent_run():
    """
    pip install gevent
    greenlet封装
    gevent.joinall(greenlets,timeout): 等待greenlets完成
    gevent.spawn(): 创建greenlet协程并与运行(g.start() return g)
    :return:
    """
    import gevent
    from gevent import monkey
    monkey.patch_all()  # 自动定位耗时的业务并切换协程任务处理 阻塞->非阻塞

    # # 方式1-串行
    # for i in range(3):
    #     g = gevent.spawn(lambda x: task_gevent(*x), (f"g{i}", i))
    #     g.join()
    #     print("returnRes=", g.value)

    # 方式2-并发
    gl = [gevent.spawn(lambda x: task_gevent(*x), (f"g{i}", i)) for i in range(3)]
    gevent.joinall(gl)
    # 获取return返回结果
    for s in gl:
        print("returnRes=", s.value)


if __name__ == '__main__':
    gevent_run()
    print(f"{os.getpid()}-{os.getppid()}-程序结束...")

image


参考文档

https://python3-cookbook.readthedocs.io/zh_CN/latest/

https://docs.python.org/3/library/concurrent.futures.html

https://www.osgeo.cn/gevent/api/gevent.html

posted @ 2023-09-13 00:42  爱编程_喵  阅读(51)  评论(0)    收藏  举报
jQuery火箭图标返回顶部代码

jQuery火箭图标返回顶部代码

滚动滑动条后,查看右下角查看效果。很炫哦!!

适用浏览器:IE8、360、FireFox、Chrome、Safari、Opera、傲游、搜狗、世界之窗.