1. 程式人生 > >Python多線程多進程

Python多線程多進程

另一個 odin 所有 單元 url 都在 sleep 簡單的 打字

一、線程&進程

對於操作系統來說,一個任務就是一個進程(Process),比如打開一個瀏覽器就是啟動一個瀏覽器進程,打開一個記事本就啟動了一個記事本進程,打開兩個記事本就啟動了兩個記事本進程,打開一個Word就啟動了一個Word進程。進程是很多資源的集合。

有些進程還不止同時幹一件事,比如Word,它可以同時進行打字、拼寫檢查、打印等事情。在一個進程內部,要同時幹多件事,就需要同時運行多個“子任務”,我們把進程內的這些“子任務”稱為線程(Thread)。

由於每個進程至少要幹一件事,所以,一個進程至少有一個線程。當然,像Word這種復雜的進程可以有多個線程,多個線程可以同時執行,多線程的執行方式和多進程是一樣的,也是由操作系統在多個線程之間快速切換,讓每個線程都短暫地交替運行,看起來就像同時執行一樣。當然,真正地同時執行多線程需要多核CPU才可能實現。線程是最小的執行單元,而進程由至少一個線程組成。

我們在做事情的時候,一個人做是比較慢的,如果多個人一起來做的話,就比較快了,程序也是一樣的,我們想運行的速度快一點的話,就得使用多進程,或者多線程,在python裏面,多線程被很多人詬病,為什麽呢,因為Python的解釋器使用了GIL的一個叫全局解釋器鎖,它不能利用多核CPU,只能運行在一個cpu上面,但是你在運行程序的時候,看起來好像還是在一起運行的,是因為操作系統輪流讓各個任務交替執行,任務1執行0.01秒,切換到任務2,任務2執行0.01秒,再切換到任務3,執行0.01秒……這樣反復執行下去。表面上看,每個任務都是交替執行的,但是,由於CPU的執行速度實在是太快了,我們感覺就像所有任務都在同時執行一樣。這個叫做上下文切換。

二、多線程,python中的多線程使用theading模塊

下面是一個簡單多線程

    import threading
    import time
    def sayhi(num): #定義每個線程要運行的函數
     
        print("running on number:%s" %num)
     
        time.sleep(3)
     
    if __name__ == __main__:
        t1 = threading.Thread(target=sayhi,args=(1,)) #生成一個線程實例
        t2 = threading.Thread(target=sayhi,args=(2,)) #
生成另一個線程實例 t1.start() #啟動線程 t2.start() #啟動另一個線程

下面是另一種啟動多線程的方式,繼承式

    import threading
    import time
    class MyThread(threading.Thread):
        def __init__(self,num):
            threading.Thread.__init__(self)
            self.num = num
     
        def run(self):#定義每個線程要運行的函數
     
            print("running on number:%s" %self.num)
    
            time.sleep(3)
     
    if __name__ == __main__:
     
        t1 = MyThread(1)
        t2 = MyThread(2)
        t1.start()
        t2.start()

這兩種方式沒有什麽區別,兩種寫法而已,我個人喜歡用第一種,更簡單一些。

線程等待,多線程在運行的時候,每個線程都是獨立運行的,不受其他的線程幹擾,如果想在哪個線程運行完之後,再做其他操作的話,就得等待它完成,那怎麽等待呢,使用join,等待線程結束

          import threading
            import time
            def run():
                print(qqq)
                time.sleep(1)
                print(done!)
            lis = []
            for i in range(5):
                t = threading.Thread(target=run)
                lis.append(t)
                t.start()
            for t in lis:
                t.join()
            print(over)    

守護線程,什麽是守護線程呢,就相當於你是一個國王(非守護線程),然後你有很多仆人(守護線程),這些仆人都是為你服務的,一但你死了,那麽你的仆人都給你陪葬。

            import threading
            import time
            def run():
                print(qqq)
                time.sleep(1)
                print(done!)
            for i in range(5):
                t = threading.Thread(target=run)
                t.setDaemon(True)
                t.start()
            print(over)

線程鎖,線程鎖就是,很多線程一起在操作一個數據的時候,可能會有問題,就要把這個數據加個鎖,同一時間只能有一個線程操作這個數據。

        import threading
        from threading import Lock
        num = 0
        lock = Lock()#申請一把鎖
        def run():
            global num
            lock.acquire()#加鎖
            num+=1
            lock.release()#解鎖
        
        lis = []
        for i in range(5):
            t = threading.Thread(target=run)
            t.start()
            lis.append(t)
        for t in lis:
            t.join()
        print(over,num)

下面來個簡單的爬蟲,看下多線程的效果

        import threading
        import requests,time
        urls  ={
            "baidu":http://www.baidu.com,
            "blog":http://www.nnzhp.cn,
            "besttest":http://www.besttest.cn,
            "taobao":"http://www.taobao.com",
            "jd":"http://www.jd.com",
        }
        def run(name,url):
            res = requests.get(url)
            with open(name+.html,w,encoding=res.encoding) as fw:
                fw.write(res.text)
        
        
        start_time = time.time()
        lis = []
        for url in urls:
            t = threading.Thread(target=run,args=(url,urls[url]))
            t.start()
            lis.append(t)
        for t in lis:
            t.join()
        end_time = time.time()
        print(run time is %s%(end_time-start_time))
       
        #下面是單線程的執行時間
        # start_time = time.time()
        # for url in urls:
        #     run(url,urls[url])
        # end_time = time.time()
        # print(‘run time is %s‘%(end_time-start_time))

三、多進程

上面說了Python裏面的多線程,是不能利用多核CPU的,如果想利用多核CPU的話,就得使用多進程,python中多進程使用multiprocessing模塊。

    from multiprocessing import Process
    import time
    def f(name):
        time.sleep(2)
        print(hello, name) 
    p = Process(target=f, args=(niu,))
    p.start()
    p.join()

Python多線程多進程