目錄
-
Python并發編程04/多線程
- 1.生產消費者模型
-
2.線程的理論知識
- 2.1什么是線程
- 2.2線程vs進程
- 2.3線程的應用
-
3.開啟進程的兩種方式
- 3.1第一種方式
- 3.2第一種方式
-
4.線程vs進程的代碼對比
- 4.1開啟速度對比
- 4.2對比pid
- 4.3同一個進程內線程共享內部數據
- 5.線程的其他方法
-
6.join與守護線程
- 6.1join
- 6.2守護線程
- 7.互斥鎖
Python并發編程04/多線程
1.生產消費者模型
#編程思想,模型,設計模式,理論等等,都是交給你一種編程的方法,以后你遇到類似的情況,套用即可.
生產者消費者模型三要素:
# 生產者: 產生數據的
# 消費者: 接收數據做進一步處理的
# 容器: 盆(隊列)
隊列容器的作用:
#起到緩沖的作用,平衡生產力與消費力,解耦.
# from multiprocessing import Process
# from multiprocessing import Queue
# import time
# import random
#
# def producer(q,name):
# for i in range(1,6):
# time.sleep(random.randint(1,2))
# res = f'{i}號包子'
# q.put(res)
# print(f'生產者{name} 生產了{res}')
#
#
# def consumer(q,name):
# while 1:
# try:
# food = q.get(timeout=3)
# time.sleep(random.randint(1, 3))
# print(f'\033[31;0m消費者{name} 吃了{food}\033[0m')
# except Exception:
# return
#
# if __name__ == '__main__':
# q = Queue()
# p1 = Process(target=producer,args=(q,'小白'))
# p2 = Process(target=consumer,args=(q,'小黑'))
# p1.start()
# p2.start()
2.線程的理論知識
2.1什么是線程
#一條流水線的工作流程.
#進程: 在內存中開啟一個進程空間,然后將主進程的所有的資源數據復制一份,然后調用cpu去執行這些代碼.
#之前的描述不夠具體:
#開啟一個進程:
#在內存中開啟一個進程空間,然后將主進程的所有的資源數據復制一份,然后調用線程去執行代碼
***進程是資源單位, 線程是執行單位.
標準描述開啟一個進程:
開啟一個進程:進程會在內存中開辟一個進程空間,將主進程的資料數據全部復制一份,線程會執行里面的代碼.
2.2線程vs進程
#1. 開啟進程的開銷非常大,比開啟線程的開銷大很多.
#2. 開啟線程的速度非常快.要快幾十倍到上百倍.
#3. 同一進程線程與線程之間可以共享數據,進程與進程之間需借助隊列等方法實現通信.
2.3線程的應用
#1. 并發: 一個cpu 看起來像是同時執行多個任務.
# 單個進程開啟三個線程.并發的執行任務.
# 開啟三個進程并發的執行任務.
# 文本編輯器:
# 1. 輸入文字.
# 2. 在屏幕上顯示.
# 3. 保存在磁盤中.
#
# 開啟多線程就非常好了:
# 數據共享, 開銷小,速度快.
#主線程子線程沒有地位之分,但是,一個進程誰在干活? 一個主線程在干活,當干完活了,你得等待其他線程干完活之后,才能結束本進程.
3.開啟進程的兩種方式
3.1第一種方式
# from threading import Thread
# import time
#
# def task(name):
# print(f'{name} is running')
# time.sleep(1)
# print(f'{name} is gone')
#
# if __name__ == '__main__':
#
# t1 = Thread(target=task,args=('二狗',))
# t1.start()
# print('===主線程') # 線程是沒有主次之分的.
3.2第一種方式
# from threading import Thread
# import time
#
# class MyThread(Thread):
#
# def __init__(self,name,l1,s1):
# super().__init__()
# self.name = name
# self.l1 = l1
# self.s1 = s1
# def run(self):
# print(f'{self.name} is running')
# time.sleep(1)
# print(f'{self.name} is gone')
#
# if __name__ == '__main__':
# t1 = MyThread('二狗', [1,2,3], '180')
# t1.start()
# print('=====主線程')
4.線程vs進程的代碼對比
4.1開啟速度對比
多進程
# from threading import Thread
# from multiprocessing import Process
# import os
#
# def work():
# print('hello')
#
# if __name__ == '__main__':
# #在主進程下開啟線程
# t=Process(target=work)
# t.start()
# print('主線程/主進程')
多線程
# from threading import Thread
# import time
#
# def task(name):
# print(f'{name} is running')
# time.sleep(1)
# print(f'{name} is gone')
#
#
# if __name__ == '__main__':
#
# t1 = Thread(target=task,args=('二狗',))
# t1.start()
# print('===主線程') # 線程是沒有主次之分的.
4.2對比pid
進程
# from multiprocessing import Process
# import time
# import os
# def task(name):
# print(f'子進程: {os.getpid()}')
# print(f'主進程: {os.getppid()}')
#
# if __name__ == '__main__':
#
# p1 = Process(target=task,args=('二狗',)) # 創建一個進程對象
# p2 = Process(target=task,args=('二狗',)) # 創建一個進程對象
# p1.start()
# p2.start()
# print(f'==主{os.getpid()}')
線程
# from threading import Thread
# import os
#
# def task():
# print(os.getpid())
#
# if __name__ == '__main__':
#
# t1 = Thread(target=task)
# t2 = Thread(target=task)
# t1.start()
# t2.start()
# print(f'===主線程{os.getpid()}')
4.3同一個進程內線程共享內部數據
# from threading import Thread
# import os
#
# x = 3
# def task():
# global x
# x = 100
#
# if __name__ == '__main__':
#
# t1 = Thread(target=task)
# t1.start()
# t1.join()
# print(f'===主線程{x}')
同一進程內的資源數據對于這個進程的多個線程來說是共享的.
5.線程的其他方法
# from threading import Thread
# from threading import currentThread
# from threading import enumerate
# from threading import activeCount
# import os
# import time
#
# def task():
# # print(currentThread())
# time.sleep(1)
# print('666')
# if __name__ == '__main__':
#
# t1 = Thread(target=task,name='線程1')
# t2 = Thread(target=task,name='線程2')
# # name 設置線程名
# t1.start()
# t2.start()
# # time.sleep(2)
# # print(t1.isAlive()) # 判斷線程是否活著
# # print(t1.getName()) # 獲取線程名
# # t1.setName('子線程-1')
# # print(t1.name) # 獲取線程名 ***
#
# # threading方法
# # print(currentThread()) # 獲取當前線程的對象
# # print(enumerate()) # 返回一個列表,包含所有的線程對象
# print(activeCount()) # ***
# print(f'===主線程{os.getpid()}')
6.join與守護線程
6.1join
join: 阻塞 告知主線程要等待我子線程執行完畢之后再執行主線程
# from threading import Thread
# import time
#
# def task(name):
# print(f'{name} is running')
# time.sleep(1)
# print(f'{name} is gone')
#
# if __name__ == '__main__':
# start_time = time.time()
# t1 = Thread(target=task,args=('二狗',))
# t2 = Thread(target=task,args=('二狗1',))
# t3 = Thread(target=task,args=('二狗2',))
#
# t1.start()
# t1.join()
# t2.start()
# t2.join()
# t3.start()
# t3.join()
#
# print(f'===主線程{time.time() - start_time}') # 線程是沒有主次之分的.
6.2守護線程
# from threading import Thread
# import time
#
# def sayhi(name):
# print('你好!')
# time.sleep(2)
# print('%s say hello' %name)
#
# if __name__ == '__main__':
# t = Thread(target=sayhi,args=('egon',))
# # t.setDaemon(True) #必須在t.start()之前設置
# t.daemon = True
# t.start() # 線程的開啟速度要跟進程開很多
#
# print('主線程')
# from threading import Thread
# import time
#
# def foo():
# print(123) # 1
# time.sleep(1)
# print("end123") # 4
#
# def bar():
# print(456) # 2
# time.sleep(3)
# print("end456") # 5
#
# t1=Thread(target=foo)
# t2=Thread(target=bar)
#
# t1.daemon=True
# t1.start()
# t2.start()
# print("main-------") # 3
結果:
123
456
main-------
end123
end456
守護線程 等待非守護子線程以及主線程結束之后,結束.
# from threading import Thread
# import time
#
# def foo():
# print(123) # 1
# time.sleep(3)
# print("end123") # 4
#
# def bar():
# print(456) # 2
# time.sleep(1)
# print("end456") # 5
#
# t1=Thread(target=foo)
# t2=Thread(target=bar)
#
# t1.daemon=True
# t1.start()
# t2.start()
# print("main-------") # 3
7.互斥鎖
# from threading import Thread
# import time
# import random
# x = 100
#
# def task():
# global x
# temp = x
# time.sleep(random.randint(1, 3))
# temp = temp - 1
# x = temp
#
#
# if __name__ == '__main__':
# l1 = []
# for i in range(100):
# t = Thread(target=task)
# l1.append(t)
# t.start()
#
# for i in l1:
# i.join()
# print(f'主線程{x}')
多個任務公搶一個數據,保證數據的安全的目的,要讓其串行
# from threading import Thread
# from threading import Lock
# import time
# import random
# x = 100
#
# def task(lock):
#
# lock.acquire()
# # time.sleep(random.randint(1,2))
# global x
# temp = x
# time.sleep(0.01)
# temp = temp - 1
# x = temp
# lock.release()
#
#
# if __name__ == '__main__':
# mutex = Lock()
# l1 = []
# for i in range(100):
# t = Thread(target=task,args=(mutex,))
# l1.append(t)
# t.start()
#
# for i in l1:
# i.join()
# print(f'主線程{x}')
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
