成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Python多線程詳細(xì)體驗(yàn)

開發(fā) 后端
線程是進(jìn)程內(nèi)部的一個(gè)執(zhí)行單元,每一個(gè)進(jìn)程至少有一個(gè)主執(zhí)行線程,它無需由用戶去主動(dòng)創(chuàng)建,是由系統(tǒng)自動(dòng)創(chuàng)建的。

線程是處理器調(diào)度和分配的基本單位,進(jìn)程則作為資源擁有的基本單位。每個(gè)進(jìn)程是由私有的虛擬地址空間、代碼、數(shù)據(jù)和其它各種系統(tǒng)資源組成。線程是進(jìn)程內(nèi)部的一個(gè)執(zhí)行單元。每一個(gè)進(jìn)程至少有一個(gè)主執(zhí)行線程,它無需由用戶去主動(dòng)創(chuàng)建,是由系統(tǒng)自動(dòng)創(chuàng)建的。用戶根據(jù)需要在應(yīng)用程序中創(chuàng)建其它線程,多個(gè)線程并發(fā)地運(yùn)行于同一個(gè)進(jìn)程中。

一、創(chuàng)建線程的方式-threading

方法1

在實(shí)例化一個(gè)線程對象時(shí),將要執(zhí)行的任務(wù)函數(shù)以參數(shù)的形式傳入threading:

# -*- coding: utf-8 -*-
import time
import threading
import datetime


def printNumber(n: int) -> None:
    while True:
        times = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        print(f'{times}-{n}')
        time.sleep(n)


for i in range(1, 3):
    t = threading.Thread(target=printNumber, args=(i,))
    t.start()

# 輸出
2022-12-16 11:04:40-1
2022-12-16 11:04:40-2
2022-12-16 11:04:41-1
2022-12-16 11:04:42-2
2022-12-16 11:04:42-1
2022-12-16 11:04:43-1
2022-12-16 11:04:44-2
2022-12-16 11:04:44-1
2022-12-16 11:04:45-1
2022-12-16 11:04:46-2
2022-12-16 11:04:46-1
2022-12-16 11:04:47-1
....
Process finished with exit code -1

創(chuàng)建兩個(gè)線程,一個(gè)線程每隔一秒打印一個(gè)“1”,另一個(gè)線程每隔2秒打印一個(gè)“2”Thread 類提供了如下的 init() 構(gòu)造器,可以用來創(chuàng)建線程:

__init__(self, group=None, target=None, name=None, args=(), kwargs=None, *,daemon=None)

此構(gòu)造方法中,以上所有參數(shù)都是可選參數(shù),即可以使用,也可以忽略。其中各個(gè)參數(shù)的含義如下:

  • group:指定所創(chuàng)建的線程隸屬于哪個(gè)線程組(此參數(shù)尚未實(shí)現(xiàn),無需調(diào)用);
  • target:指定所創(chuàng)建的線程要調(diào)度的目標(biāo)方法(最常用);
  • args:以元組的方式,為 target 指定的方法傳遞參數(shù);
  • kwargs:以字典的方式,為 target 指定的方法傳遞參數(shù);
  • daemon:指定所創(chuàng)建的線程是否為后代線程。

這些參數(shù),初學(xué)者只需記住 target、args、kwargs 這 3 個(gè)參數(shù)的功能即可。但是線程需要手動(dòng)啟動(dòng)才能運(yùn)行,threading 模塊提供了 start() 方法用來啟動(dòng)線程。因此在上面程序的基礎(chǔ)上,添加如下語句:t.start()

方法2

通過繼承 Thread 類,我們可以自定義一個(gè)線程類,從而實(shí)例化該類對象,獲得子線程。

需要注意的是,在創(chuàng)建 Thread 類的子類時(shí),必須重寫從父類繼承得到的 run() 方法。因?yàn)樵摲椒礊橐獎(jiǎng)?chuàng)建的子線程執(zhí)行的方法,其功能如同第一種創(chuàng)建方法中的 printNumber() 自定義函數(shù)。

# -*- coding: utf-8 -*-
import datetime
import time
import threading


class MyThread(threading.Thread):

    def __init__(self, n):
        self.n = n
        # 注意:一定要調(diào)用父類的初始化函數(shù)
        super().__init__()

    def run(self) -> None:
        while True:
            times = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            print(f'{times}-{self.n}')
            time.sleep(self.n)


for i in range(1, 3):
    t = MyThread(i)
    t.start()

# 輸出
2022-12-16 12:43:24-1
2022-12-16 12:43:24-2
2022-12-16 12:43:25-1
2022-12-16 12:43:26-2
2022-12-16 12:43:26-1
2022-12-16 12:43:27-1
2022-12-16 12:43:28-2
...

二、主線程和子線程

# -*- coding: utf-8 -*-
import datetime
import time
import threading


class MyThread(threading.Thread):

    def __init__(self, n):
        self.n = n
        # 注意:一定要調(diào)用父類的初始化函數(shù),否則無法創(chuàng)建線程
        super().__init__()

    def run(self) -> None:
        while True:
            _count = threading.active_count()
            threading_name = threading.current_thread().getName()
            times = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            print(f'{times}-{self.n}-"當(dāng)前活躍的線程個(gè)數(shù):{_count}"-"當(dāng)前線程的名稱是":{threading_name}')
            time.sleep(self.n)


for i in range(1, 3):
    t = MyThread(i)
    t.start()
    print(threading.current_thread().getName())

# 輸出
2022-12-16 13:18:00-1-"當(dāng)前活躍的線程個(gè)數(shù):2"-"當(dāng)前線程的名稱是":Thread-1
MainThread
2022-12-16 13:18:00-2-"當(dāng)前活躍的線程個(gè)數(shù):3"-"當(dāng)前線程的名稱是":Thread-2
MainThread

2022-12-16 13:18:01-1-"當(dāng)前活躍的線程個(gè)數(shù):3"-"當(dāng)前線程的名稱是":Thread-1
2022-12-16 13:18:02-2-"當(dāng)前活躍的線程個(gè)數(shù):3"-"當(dāng)前線程的名稱是":Thread-2
2022-12-16 13:18:02-1-"當(dāng)前活躍的線程個(gè)數(shù):3"-"當(dāng)前線程的名稱是":Thread-1
2022-12-16 13:18:03-1-"當(dāng)前活躍的線程個(gè)數(shù):3"-"當(dāng)前線程的名稱是":Thread-1
2022-12-16 13:18:04-2-"當(dāng)前活躍的線程個(gè)數(shù):3"-"當(dāng)前線程的名稱是":Thread-2
2022-12-16 13:18:04-1-"當(dāng)前活躍的線程個(gè)數(shù):3"-"當(dāng)前線程的名稱是":Thread-1
...

注意: 第一次t.start()后,當(dāng)前存在兩個(gè)線程(主線程+子線程),第二次t.start()的時(shí)候又創(chuàng)建了一個(gè)子線程所以當(dāng)前存在三個(gè)線程。

如果程序中不顯式創(chuàng)建任何線程,則所有程序的執(zhí)行,都將由主線程 MainThread 完成,程序就只能按照順序依次執(zhí)行。

此程序中,子線程 Thread-1和Thread-2 執(zhí)行的是 run() 方法中的代碼,而 MainThread 執(zhí)行的是主程序中的代碼,它們以快速輪換 CPU 的方式在執(zhí)行。

三、守護(hù)線程(Daemon Thread)

守護(hù)線程(Daemon Thread)也叫后臺進(jìn)程,它的目的是為其他線程提供服務(wù)。如果其他線程被殺死了,那么守護(hù)線程也就沒有了存在的必要。因此守護(hù)線程會(huì)隨著非守護(hù)線程的消亡而消亡。Thread類中,子線程被創(chuàng)建時(shí)默認(rèn)是非守護(hù)線程,我們可以通過setDaemon(True)將一個(gè)子線程設(shè)置為守護(hù)線程。

# -*- coding: utf-8 -*-
import datetime
import time
import threading


class MyThread(threading.Thread):

    def __init__(self, n):
        self.n = n
        # 注意:一定要調(diào)用父類的初始化函數(shù),否則無法創(chuàng)建線程
        super().__init__()

    def run(self) -> None:
        while True:
            _count = threading.active_count()
            threading_name = threading.current_thread().getName()
            times = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            print(f'{times}-{self.n}-"當(dāng)前活躍的線程個(gè)數(shù):{_count}"-"當(dāng)前線程的名稱是":{threading_name}')
            time.sleep(self.n)


for i in range(1, 3):
    t = MyThread(i)
    t.setDaemon(True)
    t.start()

    print(threading.current_thread().getName())
    
    
# 輸出
2022-12-16 13:27:46-1-"當(dāng)前活躍的線程個(gè)數(shù):2"-"當(dāng)前線程的名稱是":Thread-1
MainThread
2022-12-16 13:27:46-2-"當(dāng)前活躍的線程個(gè)數(shù):3"-"當(dāng)前線程的名稱是":Thread-2
MainThread

將兩個(gè)子線程改寫為守護(hù)線程,因?yàn)楫?dāng)主程序中的代碼執(zhí)行完后,主線程就可以結(jié)束了,這時(shí)候被設(shè)定為守護(hù)線程的兩個(gè)子線程會(huì)被殺死,然后主線程結(jié)束。

注意,當(dāng)前臺線程死亡后,Python 解釋器會(huì)通知后臺線程死亡,但是從它接收指令到做出響應(yīng)需要一定的時(shí)間。如果要將某個(gè)線程設(shè)置為后臺線程,則必須在該線程啟動(dòng)之前進(jìn)行設(shè)置。也就是說,將 daemon 屬性設(shè)為 True,必須在 start() 方法調(diào)用之前進(jìn)行,否則會(huì)引發(fā) RuntimeError 異常。

若將兩個(gè)子線程的其中一個(gè)設(shè)置為守護(hù)線程,另一個(gè)設(shè)置為非守護(hù)線程:

# -*- coding: utf-8 -*-
import datetime
import time
import threading


class MyThread(threading.Thread):

    def __init__(self, n):
        self.n = n
        # 注意:一定要調(diào)用父類的初始化函數(shù),否則無法創(chuàng)建線程
        super().__init__()

    def run(self) -> None:
        while True:
            _count = threading.active_count()
            threading_name = threading.current_thread().getName()
            times = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            print(f'{times}-{self.n}-"當(dāng)前活躍的線程個(gè)數(shù):{_count}"-"當(dāng)前線程的名稱是":{threading_name}')
            time.sleep(self.n)


for i in range(1, 3):
    t = MyThread(i)
    if i == 1:
        t.setDaemon(True)
    t.start()

    print(threading.current_thread().getName())
 
# 輸出
2022-12-16 13:30:17-1-"當(dāng)前活躍的線程個(gè)數(shù):2"-"當(dāng)前線程的名稱是":Thread-1
MainThread

2022-12-16 13:30:17-2-"當(dāng)前活躍的線程個(gè)數(shù):3"-"當(dāng)前線程的名稱是":Thread-2
MainThread

2022-12-16 13:30:18-1-"當(dāng)前活躍的線程個(gè)數(shù):3"-"當(dāng)前線程的名稱是":Thread-1
2022-12-16 13:30:19-1-"當(dāng)前活躍的線程個(gè)數(shù):3"-"當(dāng)前線程的名稱是":Thread-1
2022-12-16 13:30:19-2-"當(dāng)前活躍的線程個(gè)數(shù):3"-"當(dāng)前線程的名稱是":Thread-2
2022-12-16 13:30:20-1-"當(dāng)前活躍的線程個(gè)數(shù):3"-"當(dāng)前線程的名稱是":Thread-1
...

此時(shí)非守護(hù)線程作為前臺程序還在繼續(xù)執(zhí)行,守護(hù)線程就還有“守護(hù)”的意義,就會(huì)繼續(xù)執(zhí)行。

四、join()方法

不使用join方法

當(dāng)設(shè)置多個(gè)線程時(shí),在一般情況下(無守護(hù)線程,setDeamon=False),多個(gè)線程同時(shí)啟動(dòng),主線程執(zhí)行完,會(huì)等待其他子線程執(zhí)行完,程序才會(huì)退出。

# -*- coding: utf-8 -*-
import datetime
import time
import threading


class MyThread(threading.Thread):

    def __init__(self, n):
        self.n = n
        # 注意:一定要調(diào)用父類的初始化函數(shù),否則無法創(chuàng)建線程
        super().__init__()

    def run(self) -> None:
        _count = threading.active_count()
        threading_name = threading.current_thread().getName()
        times = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        time.sleep(1)
        print(f'{times}-{self.n}-"當(dāng)前活躍的線程個(gè)數(shù):{_count}"-"當(dāng)前線程的名稱是":{threading_name}')


start_time = time.time()
print(f'{start_time},這是主線程:', threading.current_thread().name)
for i in range(5):
    t = MyThread(i)
    # t.setDaemon(True)
    t.start()
    # t.join()
end_time = time.time()
print(f'{end_time},主線程結(jié)束了!', threading.current_thread().name)
print('一共用時(shí):', end_time - start_time)

# 輸出
1671174404.6552384,這是主線程:MainThread
1671174404.656239,主線程結(jié)束了!MainThread
一共用時(shí):0.0010006427764892578
2022-12-16 15:06:44-0-"當(dāng)前活躍的線程個(gè)數(shù):2"-"當(dāng)前線程的名稱是":Thread-1
2022-12-16 15:06:44-1-"當(dāng)前活躍的線程個(gè)數(shù):3"-"當(dāng)前線程的名稱是":Thread-2
2022-12-16 15:06:44-2-"當(dāng)前活躍的線程個(gè)數(shù):4"-"當(dāng)前線程的名稱是":Thread-3
2022-12-16 15:06:44-3-"當(dāng)前活躍的線程個(gè)數(shù):5"-"當(dāng)前線程的名稱是":Thread-4
2022-12-16 15:06:44-4-"當(dāng)前活躍的線程個(gè)數(shù):6"-"當(dāng)前線程的名稱是":Thread-5

我們的計(jì)時(shí)是對主線程計(jì)時(shí),主線程結(jié)束,計(jì)時(shí)隨之結(jié)束,打印出主線程的用時(shí)。主線程的任務(wù)完成之后,主線程隨之結(jié)束,子線程繼續(xù)執(zhí)行自己的任務(wù),直到全部的子線程的任務(wù)全部結(jié)束,程序結(jié)束。

使用join()方法

主線程任務(wù)結(jié)束之后,進(jìn)入阻塞狀態(tài),一直等待調(diào)用join方法的子線程執(zhí)行結(jié)束之后,主線程才會(huì)終止。下面的例子是讓t調(diào)用join()方法。

# -*- coding: utf-8 -*-
import datetime
import time
import threading


class MyThread(threading.Thread):

    def __init__(self, n):
        self.n = n
        # 注意:一定要調(diào)用父類的初始化函數(shù),否則無法創(chuàng)建線程
        super().__init__()

    def run(self) -> None:
        _count = threading.active_count()
        threading_name = threading.current_thread().getName()
        times = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        time.sleep(1)
        print(f'{times}-{self.n}-"當(dāng)前活躍的線程個(gè)數(shù):{_count}"-"當(dāng)前線程的名稱是":{threading_name}')


start_time = time.time()
print(f'{start_time},這是主線程:', threading.current_thread().name)
for i in range(5):
    t = MyThread(i)
    # t.setDaemon(True)
    t.start()
    t.join()
end_time = time.time()
print(f'{end_time},主線程結(jié)束了!', threading.current_thread().name)
print('一共用時(shí):', end_time - start_time)


# 輸出
1671174502.0245655,這是主線程:MainThread
2022-12-16 15:08:22-0-"當(dāng)前活躍的線程個(gè)數(shù):2"-"當(dāng)前線程的名稱是":Thread-1
2022-12-16 15:08:23-1-"當(dāng)前活躍的線程個(gè)數(shù):2"-"當(dāng)前線程的名稱是":Thread-2
2022-12-16 15:08:24-2-"當(dāng)前活躍的線程個(gè)數(shù):2"-"當(dāng)前線程的名稱是":Thread-3
2022-12-16 15:08:25-3-"當(dāng)前活躍的線程個(gè)數(shù):2"-"當(dāng)前線程的名稱是":Thread-4
2022-12-16 15:08:26-4-"當(dāng)前活躍的線程個(gè)數(shù):2"-"當(dāng)前線程的名稱是":Thread-5
1671174507.0313594,主線程結(jié)束了!MainThread
一共用時(shí):5.006793975830078

Process finished with exit code 0

join()方法的timeout參數(shù)

join的語法結(jié)構(gòu)為join(timeout=None),可以看到j(luò)oin()方法有一個(gè)timeout參數(shù),其默認(rèn)值為None,而參數(shù)timeout可以進(jìn)行賦值,其含義是指定等待被join的線程的時(shí)間最長為timeout秒,也就是說當(dāng)在timeout秒內(nèi)被join的線程還沒有執(zhí)行結(jié)束的話,就不再進(jìn)行等待了。

# -*- coding: utf-8 -*-
import datetime
import time
import threading


class MyThread(threading.Thread):

    def __init__(self, n):
        self.n = n
        # 注意:一定要調(diào)用父類的初始化函數(shù),否則無法創(chuàng)建線程
        super().__init__()

    def run(self) -> None:
        _count = threading.active_count()
        threading_name = threading.current_thread().getName()
        times = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        time.sleep(5)
        print(f'{times}-{self.n}-"當(dāng)前活躍的線程個(gè)數(shù):{_count}"-"當(dāng)前線程的名稱是":{threading_name}')


start_time = time.time()
print(f'{start_time},這是主線程:', threading.current_thread().name)
for i in range(5):
    t = MyThread(i)
    # t.setDaemon(True)
    t.start()
    t.join(2)
end_time = time.time()
print(f'{end_time},主線程結(jié)束了!', threading.current_thread().name)
print('一共用時(shí):', end_time - start_time)

# 輸出
1671175114.663927,這是主線程:MainThread
2022-12-16 15:18:34-0-"當(dāng)前活躍的線程個(gè)數(shù):2"-"當(dāng)前線程的名稱是":Thread-1
2022-12-16 15:18:36-1-"當(dāng)前活躍的線程個(gè)數(shù):3"-"當(dāng)前線程的名稱是":Thread-2
2022-12-16 15:18:38-2-"當(dāng)前活躍的線程個(gè)數(shù):4"-"當(dāng)前線程的名稱是":Thread-3
1671175124.6681008,主線程結(jié)束了!MainThread
一共用時(shí):10.004173755645752
2022-12-16 15:18:40-3-"當(dāng)前活躍的線程個(gè)數(shù):4"-"當(dāng)前線程的名稱是":Thread-4
2022-12-16 15:18:42-4-"當(dāng)前活躍的線程個(gè)數(shù):4"-"當(dāng)前線程的名稱是":Thread-5

Process finished with exit code 0
責(zé)任編輯:趙寧寧 來源: 測試玩家勇哥
相關(guān)推薦

2021-08-12 14:33:20

Python多線程編程

2022-03-09 17:01:32

Python多線程多進(jìn)程

2011-08-02 10:26:59

iOS 多線程 線程

2010-03-10 19:25:04

python多線程

2011-06-07 17:35:39

iphone 多線程

2011-07-22 14:55:20

多線程

2010-03-17 15:45:06

Java多線程求和

2023-07-27 08:59:19

線程同步Python

2011-08-31 16:22:51

LUA多線程

2011-06-24 11:03:31

Qt 多線程 線程

2011-04-18 09:22:38

多線程

2011-06-22 14:30:44

QT 多線程 線程

2009-10-10 16:15:49

VB.NET開發(fā)多線程

2010-03-15 19:11:39

Java多線程語句

2010-02-01 17:25:09

Python多線程

2009-03-12 10:52:43

Java線程多線程

2010-02-01 17:18:23

Python多線程環(huán)境

2010-03-18 16:02:09

python 多線程

2010-03-03 17:44:07

Python多線程

2012-12-25 11:39:20

Pythoncrawler
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 国产欧美在线 | 国产成人99久久亚洲综合精品 | 美女国产精品 | 国产乱码精品1区2区3区 | 亚洲国产精久久久久久久 | 中文字幕视频在线免费 | 三级特黄特色视频 | 国产区在线观看 | 四虎网站在线观看 | 伊人久久国产 | 日本一区二区高清不卡 | 精品久久久久久久久久久久久久 | 91视频网址 | 一区二区三区av | 成人国产免费视频 | 亚洲精品一区二区三区在线观看 | 精品欧美一区二区久久久伦 | 日韩欧美高清 | 日韩欧美三区 | 国产成人精品一区二区三区在线 | 成人做爰69片免费观看 | 91成人免费看片 | 日韩视频免费看 | 欧美最猛性xxxxx亚洲精品 | 看av电影 | 欧美日韩高清在线一区 | 粉嫩粉嫩芽的虎白女18在线视频 | 精品无码久久久久久国产 | 久久久久久高潮国产精品视 | 久久精品电影 | 久久精品99 | 亚洲免费高清 | 一区二区三区在线观看视频 | 久久蜜桃av | 毛片一区 | 亚洲第一色av| 国产精品久久久久久久久图文区 | www.日本在线播放 | 欧美一区免费 | 国产激情在线观看视频 | 欧美成人a |