Python基础教程之多线程与多进程
程序员文章站
2024-01-25 20:36:22
...
1.有关多线程
线程是CPU进行资源分配和调度的基本单位,共享进程的内存,一个进程必须至少有一个线程
-
基本代码示例
import threading import time def test1(): print('唱歌') def test2(): print('跳舞') task1 = threading.Thread(target = test1) task2 = threading.Thread(target = test2) task1.start() task2.start()
-
线程共享代码示例
-
正常情况下
import threading,time ticket = 10 def sale(): global ticket while True: if ticket > 0: # time.sleep(0.2) ticket -= 1 print('{0}卖了1张票,还剩下{1}张票'.format(threading.current_thread().name, ticket)) else: print('票卖完了') break task1 = threading.Thread(target=sale, name='窗口1') task2 = threading.Thread(target=sale, name='窗口2') task1.start() task2.start()
窗口1卖了1张票,还剩下9张票 窗口1卖了1张票,还剩下8张票 窗口1卖了1张票,还剩下7张票 窗口1卖了1张票,还剩下6张票 窗口1卖了1张票,还剩下5张票 窗口1卖了1张票,还剩下4张票 窗口1卖了1张票,还剩下3张票 窗口1卖了1张票,还剩下2张票 窗口1卖了1张票,还剩下1张票 窗口1卖了1张票,还剩下0张票 票卖完了 票卖完了
-
当上面的代码有time延时则会出现以下问题
窗口1卖了1张票,还剩下9张票 窗口2卖了1张票,还剩下8张票 窗口1卖了1张票,还剩下7张票 窗口2卖了1张票,还剩下6张票 窗口1卖了1张票,还剩下5张票 窗口2卖了1张票,还剩下4张票 窗口1卖了1张票,还剩下3张票 窗口2卖了1张票,还剩下2张票 窗口1卖了1张票,还剩下1张票 窗口2卖了1张票,还剩下0张票 票卖完了 窗口1卖了1张票,还剩下-1张票 票卖完了
-
-
利用线程锁来解决上面出现的问题
import threading,time ticket = 10 lock = threading.Lock() def sale(): global ticket global lock while True: # 上锁 lock.acquire() if ticket > 0: time.sleep(0.2) ticket -= 1 print('{0}卖了1张票,还剩下{1}张票'.format(threading.current_thread().name, ticket)) else: print('票卖完了') break # 解锁 lock.release() task1 = threading.Thread(target=sale, name='窗口1') task2 = threading.Thread(target=sale, name='窗口2') task1.start() task2.start()
窗口1卖了1张票,还剩下9张票 窗口2卖了1张票,还剩下8张票 窗口1卖了1张票,还剩下7张票 窗口2卖了1张票,还剩下6张票 窗口1卖了1张票,还剩下5张票 窗口2卖了1张票,还剩下4张票 窗口1卖了1张票,还剩下3张票 窗口2卖了1张票,还剩下2张票 窗口1卖了1张票,还剩下1张票 窗口2卖了1张票,还剩下0张票 票卖完了 票卖完了
-
线程之间通信的代码示例
import threading,time,queue def produce(): for i in range(1,11): time.sleep(1) print('生产出{}号产品'.format(i)) q.put('p' + str(i)) def consume(): while True: time.sleep(0.5) print('消耗掉产品' + q.get()) q = queue.Queue() task1 = threading.Thread(target=produce, name='生产者') task2 = threading.Thread(target=consume, name='消费者') task1.start() task2.start()
2.有关多进程
进程是系统进行资源分配和调度的基本单位,拥有独立的内存单元,一个程序必须至少有一个进程
-
基本代码示例
利用进程执行任务
import multiprocessing as mp import time, os def test1(n): for i in range(n): time.sleep(1) print('唱歌,进程ID:{}'.format(os.getpid())) def test2(n): for i in range(n): time.sleep(1) print('跳舞,进程ID:{}'.format(os.getpid())) if __name__ == __main__ p1 = mp.Process(target = test1, args = (10,)) p2 = mp.Process(target = test2, args = (20,)) p1.start() p2.start()
-
进程之间不共享的代码示例
进程间默认是不能共享数据的
import multiprocessing as mp import os n = 0 def test1(): global n n += 1 print('n={},进程ID:{}'.format(n, os.getpid())) def test2(): global n n += 1 print('n={},进程ID:{}'.format(n, os.getpid())) if __name__ == __main__ p1 = mp.Process(target = test1) p2 = mp.Process(target = test2) p1.start() # n=1 p2.start() # n=1
-
进程之间实现共享的代码示例
Manager对象提供了不同进程间共享数据的方式
from multiprocessing import Process, Manager def test(list): list.reverse() if __name__ == __main__ manager = Manager() list = manager.list(range(5)) p = mp.Process(target = test, args=(list,)) p.start() p.join() print(list) # [4,3,2,1,0]
-
进程之间通信的代码示例
利用Queue队列实现进程间共享数据通信
import multiprocessing as mp import os import time def produce(q): for i in range(1,11): time.sleep(1) print('生产出{}号产品,pid={}'.format(i, os.getpid())) q.put('p' + str(i)) def consume(q): while True: time.sleep(0.5) print('消耗掉{}号产品,pid={}'.format(q.get(), os.getpid())) if __name__ == '__main__' q = mp.Queue() task1 = mp.Process(target = produce, args = (q,)) task1 = mp.Process(target = consume, args = (q,)) task1.start() task2.start()
-
进程之间进行远程通信的代码示例
利用Listener和Client对象实现进程间远程通信
# 服务器端 from multiprocessing.connection import Listener listener = Listener(('127.0.0.1',8080), authkey='123') conn = listener.accept() print('连接来自:',listener.last_accepted) conn.send([1,2,3]) conn.send_bytes('hello') conn.close() listener.close()
# 客户端 from multiprocessing.connection import Client conn = Client(('127.0.0.1',8080), authkey='123') print(conn.recv()) # [1,2,3] print(conn.recv_bytes()) # hello conn.close()
-
进程池的使用代码示例
from multiprocessing import Pool import os, time, random def work(msg): start = time.time() print('执行{},进程号为{}'.format(msg,os.getpid()) time.sleep(random.random()*2) end = time.time() print('{}执行完毕,耗时{}'.format(msg,start-end)) po = Pool(3) for i in range(0,10): po.apply_async(work,(i,)) po.close() po.join()
下一篇: IIS部署ASP.NET5的实现步骤