Python: 线程之间通信(源码拷贝即用)
目录
一、线程之间的几种通信方式
二、Lock()
三、Condition()
四、Event()
五、Queue
一、线程之间的几种通信方式
threading.Lock()/threading.RLock() - 互斥锁,在某一时刻只能有一个使用者访问该资源
threading.Condition() - 资源锁,可以提供挂起/唤醒等功能
threading.Event() - 事件,也可以提供类似资源锁的挂起/唤醒功能
Queue - 队列
二、Lock()
import threading
 
class MyThread(threading.Thread):
    def __init__(self, mutex, arg):
        threading.Thread.__init__(self, daemon=True)
        self.mutex = mutex
        self.arg = arg
 
    def run(self):
        for i in range(10000):
            self.mutex.acquire()
            self.arg['count'] = self.arg.get('count', 0) + 1
            self.mutex.release()
 
        self.mutex.acquire()
        self.arg['done'] = self.arg.get('done', 0) + 1
        self.mutex.release()
 
 
def main():
    mutex = threading.Lock()
    arg = dict()
    n = 100
    for i in range(n):
        t = MyThread(mutex, arg)
        t.start()
 
    import time
    while True:
        print("count = [{0}], done = [{1}]".format(arg.get('count', -1), arg.get('done', -1)))
        if arg.get('done', 0) == n:
            break
        time.sleep(1)
 
if "__main__" == __name__:
    main()
三、Condition()
import time
import random
import threading
 
class NotiyThread(threading.Thread):
    def __init__(self, name, cond):
        threading.Thread.__init__(self)
        self.cond = cond
        self.name = name
 
    def run(self):
        # 等待 wait 线程的 wait() 操作,notify() 操作必须能满足所有的 wait() 操作,否则 wait 线程会卡住一直等待
        time.sleep(random.randint(10, 11))
        for i in range(3 * 5): # notify 3 * 15 次,因为5个 wait 线程,每个 wait 3 次
            print("thread-{0} - {1} - send notify".format(self.name, i))
            self.cond.acquire()
            self.cond.notify()
            self.cond.release()
            print("thread-{0} - {1} - send notify ok".format(self.name, i))
            time.sleep(random.randint(1, 2))
        print("thread-{0} over".format(self.name))
 
 
class WaitThread(threading.Thread):
    def __init__(self, name, cond):
        threading.Thread.__init__(self)
        self.cond = cond
        self.name = name
 
    def run(self):
        time.sleep(random.randint(1, 3))
        for i in range(3): # wait 3 次
            print("thread-{0} - {1} - wait for notify ...".format(self.name, i))
            self.cond.acquire()
            self.cond.wait()
            self.cond.release()
            print("thread-{0} - {1} - get notify !".format(self.name, i))
        print("thread-{0} over".format(self.name))
 
 
def main():
    tlist = list()
    n = 5
    cond = threading.Condition()
    t = NotiyThread('notify', cond)
    tlist.append(t)
    for i in range(n):
        t = WaitThread('wait-' + str(i), cond)
        tlist.append(t)
 
    for t in tlist:
        t.start()
 
    for t in tlist:
        print("waitting for {0} end".format(t.name))
        t.join() # 等待线程结束
 
 
if "__main__" == __name__:
    main()
四、Event()
from queue import Queue, Empty
import threading
import time
import random
 
class Task(object):
    def __init__(self, event, option=''):
        self.event = event
        self.option = option
        self.data = None
 
 
class ReadFileThread(threading.Thread):
    def __init__(self, q):
        threading.Thread.__init__(self)
        self.q = q
 
    def run(self):
        for i in range(5):
            time.sleep(random.randint(1, 3))
            task = None
            try:
                task = self.q.get(timeout=10)
                if 'readfile' == task.option:
                    task.data = 'file content:' + str(random.randint(100, 200))
                task.event.set()
            except Empty as e:
                print("queue is empty before timeout:", str(e))
 
 
class PrintThread(threading.Thread):
    def __init__(self, q):
        threading.Thread.__init__(self)
        self.q = q
 
    def run(self):
        for i in range(5):
            task = Task(threading.Event(), option='readfile')
            self.q.put(task)
            task.event.wait()
            print("get file data: [{0}]".format(task.data))
 
 
def main():
    q = Queue()
    reader = ReadFileThread(q)
    printer = PrintThread(q)
 
    reader.start()
    printer.start()
 
    printer.join()
    reader.join()
    print("exit")
 
 
if "__main__" == __name__:
    main()
五、Queue
一个线程向 queue put 资源,另一个线程 get 资源。
from queue import Queue, Empty
import threading
import time, random
 
 
class Writer(threading.Thread):
    def __init__(self, q):
        threading.Thread.__init__(self, daemon=True)
        self.q = q
        self.done = False
 
    def run(self):
        for i in range(10):
            p = 'product-' + str(i)
            print("make product : [{0}]".format(p))
            self.q.put(p)
            time.sleep(random.randint(1, 3))
        self.done = True
 
 
class Reader(threading.Thread):
    def __init__(self, q):
        threading.Thread.__init__(self, daemon=True)
        self.q = q
        self.done = False
 
    def run(self):
        while True:
            try:
                d = self.q.get(timeout=5)
                print('get product :', d)
            except Empty as e:
                print("no product get")
                break
        self.done = True
 
 
def main():
    q = Queue()
    maker = Writer(q)
    reader = Reader(q)
 
    maker.start()
    reader.start()
 
    while True:
        time.sleep(1)
        if maker.done == True and reader.done == True:
            print("maker and reader is done, quit")
            break
 
 
if "__main__" == __name__:
    main()
————————————————
版权声明:本文为CSDN博主「miaow~miaow」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/fengbohello/article/details/121522001
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号