1. 程式人生 > >python中線程和進程(一)

python中線程和進程(一)

輕量級 輕量 調度 寄存器 readn 必須 RKE 線程終止 ogg

目錄

  • 進程和線程
  • Python中的線程
    • 1. Thread類
    • 2. 線程的啟動
    • 3. 線程的傳參
    • 4. 線程的屬性和方法
    • 5. daemon線程和non-daemon線程
    • 6. join方法
    • 7. 定時器Timer

進程和線程

  • 進程:進程是計算機中程序正在執行的實例,是系統進行資源分配和調度的基本單位。
  • 線程:也被稱為輕量級進程,是程序執行流的最小單元。一個標準的線程由線程ID,當前指令指針,寄存器集合和堆棧組成。

線程和進程的關系:

現代操作系統中,每一個進程都認為自己獨占所有的計算機資源。進程好比一個國家,各個進程間不可以隨便的共享數據,而線程就像是省份,同一個進程內的線程可以共享進程的資源,每一個線程擁有自己獨立的堆棧。

技術分享圖片

進程和程序的關系:

程序是源代碼編譯後的文件,當該程序被操作系統加載到內存中,就是進程,進程中存放著指令和數據,它也是線程的容器。

Python中的線程

1. Thread類

python中線程的開發使用標準庫:threading

def __init__(self, group=None, target=None, name=None,
             args=(), kwargs=None, *, daemon=None):
  • target:線程調用的對象,即目標函數
  • name: 線程名
  • args:為目標函數傳遞的實參,元組
  • kwargs:為目標函數關鍵字傳參,字典

2. 線程的啟動

import threading


def worker():
    print("I'm working")
    print("Finished")

t = threading.Thread(target=worker,name='worker') #創建線程對象
t.start() # 啟動線程

可以通過threading.Thread創建一個線程對象,target指定目標函數,然後調用start

方法進行啟動線程。

3. 線程的傳參

import threading
import time


def add(x,y):
    print("{} + {} = {}  線程ID:{}".format(x,y,x+y,threading.current_thread().ident))

thread1 = threading.Thread(target=add,name='add1',args=(4,5)).start()
time.sleep(1)
thread2 = threading.Thread(target=add,name='add2',args=(10,),kwargs={'y':5}).start()
time.sleep(1)
thread3 = threading.Thread(target=add,name='add3',kwargs={'x':20,'y':5}).start()

線程傳參和函數傳參沒有什麽區別,本質上就是函數傳參。

4. 線程的屬性和方法

threading的屬性和方法

名稱 含義
current_thread() 返回當前線程對象
main_thread() 返回主線程對象
active_count() 當前處於alive狀態的線程數
enumerate() 返回所有活著的線程的列表,不包括已經終止的線程和為開始的線程
get_ident() 返回當前線程的ID

Thread實例的屬性和方法

名稱 含義
name 名稱,僅僅是一個標識。可以通過getName()獲取,setName()設置該名稱
ident 線程ID
is_alive() 返回線程是否活著
start() 啟動線程。每個線程必須且只能執行該方法一次
run() 運行線程函數

start和run的區別:
使用start啟動線程,會啟動一個新的線程,而使用run方法,並沒有啟動新的線程,只有在主線程上調用一個普通的函數。

5. daemon線程和non-daemon線程

在Python中,構造線程時,可以設置daemon屬性。默認daemon線程是None,即non-daemon線程。

import time
import threading


def foo():
    time.sleep(5)
    for i in range(20):
        print(i)

t = threading.Thread(target=foo,daemon=True) #修改成None
t.start()
print("main thread Exit")

如果一個程序中只有daemon線程,那麽主線程退出的時候,會結束所有的daemon線程,退出。
總結:
在一個程序中,如果有non-daemon線程的時候,主線程退出時,不會殺掉所有的daemon線程,直到所有的non-daemon線程全部結束,如果還有daemon線程,主線程退出的時候,會結束所有的daemon線程,然後退出。

6. join方法

import time
import threading


def foo(n):
    for i in range(n):
        print(i)
        time.sleep(1)

t = threading.Thread(target=foo,args=(10,),daemon=True)
t.start()
t.join() # 設置join
print("main thread Exit")

設置join後,daemon線程執行完了,程序才會退出。
join(timeout=None):
一個線程中調用另一個線程的join方法,此時調用者將會被阻塞,直到被調線程終止。一個線程可以被join多次。調用誰的join方法,就要等誰。

import time
import threading


def bar():
    while True:
        time.sleep(1)
        print("bar")


def foo():
    print("t1's daemon = {}".format(threading.current_thread().isDaemon()))
    t2 = threading.Thread(target=bar)
    t2.start()
    print("t2's daemon = {}".format(t2.isDaemon()))


t1 = threading.Thread(target=foo,daemon=True)
t1.start()
time.sleep(3)
print("main thread exiting")

只要主程序退出,2個工作線程就結束。

import time
import threading


def bar():
    while True:
        time.sleep(1)
        print("bar")


def foo():
    print("t1's daemon = {}".format(threading.current_thread().isDaemon()))
    t2 = threading.Thread(target=bar)
    t2.start()
    print("t2's daemon = {}".format(t2.isDaemon()))
    t2.join()


t1 = threading.Thread(target=foo,daemon=True)
t1.start()
t1.join()
time.sleep(3)

print("main thread exiting")

通過相互調用join方法,使線程結束不了。

7. 定時器Timer

class Timer(Thread):
    def __init__(self, interval, function, args=None, kwargs=None):

threading.Timer繼承自Thread,該類用來定義多久執行一個函數。
start方法執行之後,Timer對象就會處於等待狀態,等待了interval之後,開始執行function函數,如果在執行函數之前的等待階段,使用了cancel方法,就會跳過執行函數。
但是如果線程中的函數已經開始執行,cancel就沒有效果了。

import threading
import logging
import time


FORMAT = '%(asctime)s %(threadName)s %(thread)d %(message)s'
logging.basicConfig(format=FORMAT,level=logging.INFO)


def worker():
    logging.info('in worker')
    time.sleep(2)

t = threading.Timer(5,worker)
t.setName('w1')
t.cancel()  # 提前取消
t.start()
print(threading.enumerate())
time.sleep(8)
print(threading.enumerate())

python中線程和進程(一)