• python——进程、线程、协程


    说明

    1、一个应用程序,默认单进程,单线程;
    2、python GIL,全局解释器锁,cpu每次只能执行一个进程中的一个线程。
    3、多进程,多线程:
      IO操作使用多线程可以提高效率;
      计算型操作使用多进程可以提高效率。

    一、线程

    创建线程

    import threading
    
    def f1(arg):
        print(arg)
    
    t = threading.Thread(target=f1,args=(123,)) #创建线程,让线程执行f1,f1的参数为123
    t.start()   #当前线程并不一定会立即执行,要等待CPU调度

    threading基本用法

    import time
    def f1(a):
        time.sleep(1)
        print(a)
    
    import threading
    t = threading.Thread(target=f1,args=('ss')) #创建线程,让线程执行f1,f1的参数为'ss'
    t.setDaemon(True)   #true,表示主线程不等该子线程,主线程执行结束直接退出。默认False
    t.start()   #当前线程并不一定会立即执行,要等待CPU调度
    t.join(2)    #表示主线程在此等待,直到子线程结束,最多等2秒
    print('end')

    自定义线程类

    import threading
    class MyThread(threading.Thread):
        def __init__(self,func,args):
            self.func = func
            self.args = args
            super(MyThread,self).__init__() #主动执行父类的构造方法
    
        def run(self):  #run方法会自动执行
            self.func(self.args)
    
    def f(arg):
        print(arg)
    
    obj = MyThread(f,"ss")
    obj.start()

     

    FIFO队列

    先进先出,基础队列。在内存中创建的队列

    import queue
    q = queue.Queue(10) #建立队列,队列最大长度为10,超过则阻塞或报错
    q.put(11)   #队列放数据
    q.put(22,block=False)   #不阻塞,直接报错
    q.put(33,timeout=2) #等待两秒,两秒之后报错
    
    print(q.qsize())    #打印队列长度
    
    print(q.get())  #队列取数据
    print(q.get(timeout=2)) #等待两秒,两秒之后报错
    print(q.get(block=False))   #不阻塞,直接报错

    其他队列

    queue.LifoQueue()   #后进先出队列
    queue.PriorityQueue()   #优先级队列
    queue.deque()   #双向队列

    生产者消费者模型

    import threading,queue
    q = queue.Queue(20)
    def productor(arg):    #生产者
        while True:
            q.put(str(arg)+' ss')
    
    def consumer(arg): #消费者
        while True:
            print(arg,q.get())
    
    for i in range(20):
        t = threading.Thread(target=productor,args=(i,))
        t.start()
    
    for j in range(3):
        t = threading.Thread(target=consumer,args=(j,))
        t.start()

    线程锁

    import threading,time
    NUM=10
    
    def func(lock):
        global NUM
        lock.acquire()  #上锁
        NUM -= 1
        time.sleep(2)
        print(NUM)
        lock.release()  #开锁
    
    lock = threading.Lock() #互斥锁,每次只能执行一个线程
    #lock = threading.RLock()    #支持多层锁嵌套
    #lock = threading.BoundedSemaphore(5)    #最多允许5个线程同时允行
    
    for i in range(10):
        t = threading.Thread(target=func,args=(lock,))
        t.start()
    import threading
    
    def func(i,event):
        print(i)
        event.wait()    #检测,如果是clear()则停,如果是set()则继续执行。
        print(i+100)
    
    event=threading.Event() #批量锁住所有线程
    
    for i in range(10):
        t = threading.Thread(target=func,args=(i,event,))
        t.start()
    
    event.clear()   #设置成
    inp = input('>>>')
    if inp=='1':
        event.set()
    import threading
    
    def func(i,con):
        print(i)
        con.acquire()   #上锁
        con.wait()  #等待notify,notify(2)则释放两个线程锁
        print(i+100)
        con.release()
    
    con = threading.Condition() #条件锁,notify(n)决定释放几个锁
    
    for i in range(10):
        t = threading.Thread(target=func,args=(i,con,))
        t.start()
    
    while True:
        inp = input('>>>')
        if inp == 'q':
            break
        con.acquire()
        con.notify(int(inp))
        con.release()
        #上面三句固定写法
    import threading
    
    def condition():
        ret = False
        r = input('>>>')
        if r == 'true':
            ret = True
        else:
            ret = False
        return ret
    
    def func(i,con):
        print(i)
        con.acquire()   #上锁
        con.wait_for(condition)  #等待condition函数的执行结果,返回true则释放一个锁
        print(i+100)
        con.release()
    
    con = threading.Condition() #条件锁,notify(n)决定释放几个锁
    
    for i in range(10):
        t = threading.Thread(target=func,args=(i,con,))
        t.start()

    Timer

    from threading import Timer
    
    def hello():
        print('hello world')
    
    t = Timer(1,hello)
    t.start()   #1秒钟之后执行hello函数

    线程池

    import queue
    import threading
    import time
    class ThreadPool:
        def __init__(self,maxsize):
            self.maxsize = maxsize
            self._q = queue.Queue(maxsize)
            for i in range(maxsize):
                self._q.put(threading.Thread)   #把线程放入队列
    
        def get_thread(self):
            return self._q.get()
    
        def add_thread(self):
            self._q.put(threading.Thread)
    
    pool = ThreadPool(5)
    
    def task(arg,p):
        print(arg)
        time.sleep(1)
        p.add_thread()
    
    for i in range(100):
        t = pool.get_thread()
        obj = t(target=task,args=(i, pool,))
        obj.start()
    import queue
    import threading
    import contextlib
    import time
    
    StopEvent = object()    #空值,用于终止线程任务
    
    
    class ThreadPool(object):
    
        def __init__(self, max_num, max_task_num = None):
            if max_task_num:
                self.q = queue.Queue(max_task_num)
            else:
                self.q = queue.Queue()
            self.max_num = max_num
            self.cancel = False
            self.terminal = False
            self.generate_list = []
            self.free_list = []
    
        def run(self, func, args, callback=None):
            """
            线程池执行一个任务
            :param func: 任务函数
            :param args: 任务函数所需参数
            :param callback: 任务执行失败或成功后执行的回调函数,回调函数有两个参数1、任务函数执行状态;2、任务函数返回值(默认为None,即:不执行回调函数)
            :return: 如果线程池已经终止,则返回True否则None
            """
            if self.cancel:
                return
            if len(self.free_list) == 0 and len(self.generate_list) < self.max_num:
                self.generate_thread()
            w = (func, args, callback,) #把三个函数放到一个元组里,作为一个任务
            self.q.put(w)   #把任务放入队列
    
        def generate_thread(self):
            """
            创建一个线程
            """
            t = threading.Thread(target=self.call)  #线程执行call方法
            t.start()
    
        def call(self):
            """
            循环去获取任务函数并执行任务函数
            """
            current_thread = threading.currentThread()  #获取当前线程
            self.generate_list.append(current_thread)   #把当前线程加入generate_list
    
            event = self.q.get()    #从队列中取出任务
            while event != StopEvent:
    
                func, arguments, callback = event
                try:
                    result = func(*arguments)
                    success = True
                except Exception as e:
                    success = False
                    result = None
    
                if callback is not None:
                    try:
                        callback(success, result)
                    except Exception as e:
                        pass
    
                with self.worker_state(self.free_list, current_thread):
                    if self.terminal:
                        event = StopEvent
                    else:
                        event = self.q.get()
            else:
    
                self.generate_list.remove(current_thread)
    
        def close(self):
            """
            执行完所有的任务后,所有线程停止
            """
            self.cancel = True
            full_size = len(self.generate_list)
            while full_size:
                self.q.put(StopEvent)
                full_size -= 1
    
        def terminate(self):
            """
            无论是否还有任务,终止线程
            """
            self.terminal = True
    
            while self.generate_list:
                self.q.put(StopEvent)
    
            self.q.queue.clear()
    
        @contextlib.contextmanager
        def worker_state(self, state_list, worker_thread):
            """
            用于记录线程中正在等待的线程数
            """
            state_list.append(worker_thread)
            try:
                yield
            finally:
                state_list.remove(worker_thread)
    
    
    
    # How to use
    
    
    pool = ThreadPool(5)
    
    def callback(status, result):
        # status, execute action status
        # result, execute action return value
        pass
    
    
    def action(i):
        print(i)
    
    for i in range(30):
        ret = pool.run(action, (i,), callback)
    
    time.sleep(5)
    print(len(pool.generate_list), len(pool.free_list))
    print(len(pool.generate_list), len(pool.free_list))
    # pool.close()
    # pool.terminate()

    二、进程

    创建子进程,子进程间数据共享

    进程操作尽量不在windows环境下使用

    from multiprocessing import Process
    from multiprocessing import queues
    import multiprocessing
    
    def foo(i,li):
        li.put(i)
        print('say hi', i,li.qsize())
    
    li = queues.Queue(20,ctx=multiprocessing)   #特殊的队列,子进程间数据共享
    for i in range(10):
        p = Process(target=foo, args=(i,li,))   #多进程执行foo函数
        p.start()
    from multiprocessing import Process
    from multiprocessing import Manager
    
    def Foo(i,dic):
        dic[i] = 100 + i
        print(dic.values())
    
    
    manage = Manager()  #创建对象
    dic = manage.dict()  #主进程建立特殊的字典,用于子进程间数据共享
    for i in range(10):
        p = Process(target=Foo, args=(i,dic))
        p.start()
        p.join()    #主进程等待子进程都结束

    进程锁

    进程锁用法和线程一样。

    进程池

    from multiprocessing import Pool
    
    def foo(arg):
        print(arg)
    
    if __name__=="__main__":
        pool = Pool(5)
        for i in range(30):
            #pool.apply(func=foo,args=(i,))    #去进程池中取进程,串行执行foo
            pool.apply_async(func=foo,args=(i,))    #非阻塞异步执行
        pool.close()
        pool.join() #与上一行一起,表示等待所有子进程全部执行完毕

    三、协程

    利用一个线程,分解一个线程成为多个微线程
    pip3 install gevent
    gevent使用greenlet库完成协程操作

    from greenlet import greenlet
    
    def test1():
        print(12)
        gr2.switch()
        print(34)
        gr2.switch()
    
    def test2():
        print(56)
        gr1.switch()
        print(78)
    
    gr1 = greenlet(test1)
    gr2 = greenlet(test2)
    gr1.switch()
    from gevent import monkey; monkey.patch_all()
    import gevent
    import requests
    
    def f(url):
        print('GET: %s' % url)
        resp = requests.get(url)
        data = resp.text
        print('%d bytes received from %s.' % (len(data), url))
    
    gevent.joinall([
            gevent.spawn(f, 'https://www.python.org/'),
            gevent.spawn(f, 'https://www.baidu.com/'),
            gevent.spawn(f, 'https://github.com/'),
    ])
  • 相关阅读:
    Connection with Web.config
    sp_user_no(參數數的oracle_sp)及fn_test(有返回值的oracle參數)
    xml學習心得
    OOP 术语:Attributes(特性)与 Properties(属性)的区别(转载)
    asp.net 4.0 新特性(转载)
    详解C#中Attribute特性应用 (转载)
    保存web.config文件(转载)
    OOP 术语:Arguments(参量)和 Parameters(参数)的区别(转载)
    HTTP调试工具:Fiddler,httpwatch 介绍(转)
    C# 4.0新特性dynamic有何用处?(转载)
  • 原文地址:https://www.cnblogs.com/maxgongzuo/p/7486229.html
Copyright © 2020-2023  润新知