spider ---- 程序&執行緒+++多程序&多執行緒
-
1案例演示:
-
程序-面向過程
import time from multiprocessing import Process def sing(): for x in range(1, 6): print('你在唱女兒情') time.sleep(1) def dance(): for x in range(1, 6): print('你在跳小蘋果') time.sleep(1) def main(): # 建立兩個程序,分別執行一個函式 p_dance = Process(target=dance) p_sing = Process(target=sing) # 啟動程序,兩個子程序 p_dance.start() p_sing.start() # 主程序需要等待子程序結束在結束 p_dance.join() p_sing.join() print('主程序,子程序全部執行結束') if __name__ == '__main__': main()
程序-面向物件:
import time from multiprocessing import Process class SingProcess(Process): def __init__(self, name): super().__init__() self.name = name # 重寫run方法,函式名字為run不能更改 def run(self): for x in range(1, 6): print('%s在讀紅樓夢' % self.name) time.sleep(1) class DanceProcess(Process): def run(self): for x in range(1, 6): print('你在跳鋼管舞') time.sleep(1) def main(): name = '郭襄' p_sing = SingProcess(name) p_dance = DanceProcess() p_sing.start() p_dance.start() p_sing.join() p_dance.join() print("主程序,子程序執行結束") if __name__ == '__main__': main()
程序池演示:
import os import random import time from multiprocessing import Pool def demo(name): print('%s---任務正在執行,程序id號---%s' % (name, os.getpid())) lt = [1, 2, 3] time.sleep(random.choice(lt)) def main(): # 建立程序池 物件 pol = Pool(3) # 最多建立3個程序 # 任務名字列表 lt = ['楊過', '陽頂天', '獨孤求敗', '雕兄', '虛竹', '段正淳', '段譽', '令狐沖', '周伯通', '金輪法王'] # 迴圈給池子新增任務 for name in lt: pol.apply_async(demo, args=(name,)) # 關閉池子不再新增 pol.close() # 主程序等待程序池裡面所有的程序結束之後在結束 pol.join() print('主程序,子程序全部執行結束') if __name__ == '__main__': main()
-
2、多工
多個任務同時執行
生活中:唱歌跳舞、開車手腳並用
計算機中:瀏覽器、sublime、vnc、錄屏,多個任務都在同時執行
程式碼中:寫一個段程式碼,一個函式可以稱之為一個任務。
要想實現多工同時執行:多程序、多執行緒
四個關鍵字
同步 執行完任務a才能執行任務b
非同步 執行任務a的同時也執行任務b
並行 任務a和任務b真的在同時執行 真非同步
併發 任務a和任務b在一段時間在同時執行 偽非同步
3、多程序(process)
怎麼理解程序?
在電腦中,啟動一個軟體,系統就會分配一個程序
在程式碼中,寫好的程式碼沒有執行之前稱之為程式,執行的時候就是一個程序
以前寫的程式碼都只有一個主程序,需要通過主程序來建立其他的子程序
程序建立
(1)面向過程
p = Process(target=xxx, args=(xxx,))
target: 程序啟動之後要執行的函式
args: 主程序給子程序傳遞的引數
p.start() 啟動程序
p.join() 讓主程序等待
os.getpid() 獲取當前程序id號
os.getppid() 獲取父程序id號
(2)面向物件
class MyProcess(Process):
def run(self):
pass
程序啟動執行run方法,如果需要傳參,需要重寫構造方法,在構造方法中要記得手動呼叫父類的構造方法
程序之間是否共享區域性變數
不共享
程序之間是否共享全域性變數
不共享
程序之間不共享任何資料
程序池
請問:程序是不是建立的越多越好?
小例子:比如給一個資料夾,資料夾裡面有100個檔案
copy(src, dst)
不是絕對的。要開闢多少個程序拷貝呢?
開闢5個程序,實現100個檔案的拷貝
最多開闢5個程序,這個東西我們稱之為程序池
4、多執行緒(thread)
如何理解執行緒?
比如在qq裡面,可以同時語音和視訊,在word裡面,可以同時打字、拼寫檢查
這些同時執行的就可以理解為執行緒
多工-多程序、多執行緒
程序和執行緒的區別
(1)執行緒屬於程序,一個執行緒只能屬於一個程序,一個程序裡面可以有多個執行緒。
(2)系統分配資源的基本單位是程序。
(3)系統排程資源的基本單位是執行緒。
畫圖理解
以前的程式只有一個程序,主程序,在這個程序裡面只有一個執行緒,主執行緒
建立執行緒
(1)面向過程建立
t = threading.Thread(target=xxx, name=xxx, args=(xxx,))
target: 執行緒啟動要執行的函式
name: 給執行緒起名字 threading.current_thread().name
args: 主執行緒給子執行緒傳遞引數
t.start()
t.join()
(2)面向物件建立
執行緒之間是否共享區域性變數
不共享
執行緒之間是否共享全域性變數
共享
執行緒安全、執行緒同步
a += 1
多個執行緒往同一個檔案中寫內容
鎖,獨自使用,開鎖,
在操作之前加鎖,然後操作,操作完畢之後,釋放鎖
上鎖的時候是搶的。
犧牲了效能。
from threading import Lock
# 建立一把鎖, 多個執行緒使用一把鎖
lock = Lock()
# 上鎖
lock.acquire()
# 釋放鎖
lock.release()
5、佇列
生活中:買火車票,佇列特點:先進先出
棧:先進後出
程式中: from queue import Queue
q = Queue(5)
q.put(xxx) 新增元素
q.get() 獲取元素
q.full() 判斷佇列是否滿
q.empty() 判斷佇列是否為空
q.qsize() 得到佇列中元素的個數
6、多執行緒爬蟲
執行緒和佇列,生產者消費者模型
while 1:
生產資料
消費資料生產資料執行緒
資料佇列
消費資料執行緒到爬蟲中
for page in range(1, 11):
拼接url,傳送請求,得到響應
資料佇列
解析響應,儲存資料