Python並行編程(一):線程的基本概念和線程的兩種定義方法以及join()、setDaemon(True)的使用

前言:本系列將包含Python並行編程的相關技術內容,包括Python線程、Python進程、併發編程的異步模式及終極大法Python分佈式計算如Celery、SCOOP等相關技術。

關鍵詞: threading multiprocessing asyncio Celery


線程的基本概念和線程的兩種定義方法

線程是什麼?

線程看起來就像輕量級的進程,而進程又是什麼呢? 進程即咱們平時運行程序,好比經過點擊圖標打開的瀏覽器,QQ都是進程,進程擁有本身的獨立的內存空間地址,能夠擁有多個線程;即線程是存在進程內,也就意味着一個進程內的線程能夠共享一些資源,其線程間的切換也就比進程低得多,多個線程能夠並行及併發執行,共享數據和資源,因此咱們多數時候的線程通訊都是利用共享信息的空間進行通訊,這也是後面談到的線程管理必備的多種線程通訊方式了。python

在Python怎麼定義線程?

使用線程最簡單的方式就是經過目標函數的實例化:

import threading
import time


# 用於實例化線程目標函數
def function(i):
    time.sleep(2)
    print('Thread {} is running.'.format(i))
    time.sleep(2)
    return


for i in range(5):
    # Python模塊threading.Thread方法
    t = threading.Thread(target=function, args=(i, ))
    t.start()
複製代碼

運行截圖以下: 編程

運行截圖
經過以上程序咱們看出,定義好咱們須要運行的目標函數來實例化線程,而後傳入參數 target即函數名,而後若是須要運行的目標函數有參數須要傳遞的話便可傳入 args元組,注意此處傳入的是 元組tuple。 而後咱們在調用 start()方法後啓動實例化的線程

使用線程模塊實現新的線程:

import threading
import time


class myThread(threading.Thread):
    def __init__(self, i):
        threading.Thread.__init__(self)
        self.i = i

    def run(self):
        time.sleep(2)
        print('Thread {} is running.'.format(self.i))
        time.sleep(2)
        return


for i in range(1, 6):
    t = myThread(i)
    t.start()
複製代碼

運行截圖以下: 瀏覽器

運行截圖
經過上面的程序咱們能夠看出,咱們須要定義新的Thread類的子類,而且經過重寫 __init__方法來傳遞參數,而後重寫 run()方法來實現目標函數,那麼當咱們建立出新的子類後就能夠實例化該子類並經過 start()方法來啓動線程。

守護線程 setDaemon(True)

接下來咱們在運行一段代碼:多線程

import threading
import time


class myThread(threading.Thread):
    def __init__(self, i):
        threading.Thread.__init__(self)
        self.i = i

    def run(self):
        time.sleep(2)
        print('Thread {} is running.'.format(self.i))
        time.sleep(2)
        return

print('Mian THread starting')

for i in range(1, 6):
    t = myThread(i)
    t.start()
    
print('Mian THread end')
複製代碼

運行截圖以下: 併發

運行截圖
當一個進程啓動以後,會默認產生一個主線程,由於線程是程序執行流的最小單元,當設置多線程時,主線程會建立多個子線程;咱們在主線程添加了兩句 print()用於打印主線程的運行狀態,咱們能夠看見在默認狀況下主現成直接執行完就退出了,此時子線程們還在執行過程當中,那麼若是咱們添加setDaemon(True)方法呢:

import threading
import time


class myThread(threading.Thread):
    def __init__(self, i):
        threading.Thread.__init__(self)
        self.i = i

    def run(self):
        time.sleep(2)
        print('Thread {} is running.'.format(self.i))
        time.sleep(2)
        return

print('Mian THread starting')

for i in range(1, 6):
    t = myThread(i)
    t.setDaemon(True)
    t.start()
    
print('Mian THread end')
複製代碼

運行截圖以下: app

運行截圖
咱們能夠在運行截圖中看到,當咱們使用setDaemon(True)方法,設置子線程爲守護線程時,主線程一旦執行結束,則所有線程所有被終止執行,可能出現的狀況就是,子線程的任務尚未徹底執行結束,就被迫中止。 那麼咱們能不能讓主線程等等咱們的子線程,等待子線程運行結束後,主線程再終止呢,即實現守護線程相反的效果,答案是能夠得。

阻塞線程 join()

import threading
import time


class myThread(threading.Thread):
    def __init__(self, i):
        threading.Thread.__init__(self)
        self.i = i

    def run(self):
        time.sleep(2)
        print('Thread {} is running.'.format(self.i))
        time.sleep(2)
        return


print('Mian THread starting')

threads = []
for i in range(1, 6):
    t = myThread(i)
    t.start()
    threads.append(t)

for t in threads:
    t.join()
    
print('Mian THread end')

複製代碼

運行截圖以下: 異步

運行截圖
咱們能夠看見主線程是在等待子線程運行結束才終止運行的,即 join()所完成的工做就是線程同步,即主線程任務結束以後,進入阻塞狀態,一直等待其餘的子線程執行結束以後,主線程再終止。
相關文章
相關標籤/搜索