小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Python建立多線程任務(wù)并獲取每個線程返回值

 XiaopanLyu 2019-07-19

1.進程和線程

    (1)進程是一個執(zhí)行中的程序。每個進程都擁有自己的地址空間、內(nèi)存、數(shù)據(jù)棧以及其他用于跟蹤執(zhí)行的輔助數(shù)據(jù)。進程也可以派生新的進程來執(zhí)行其他任務(wù),不過每個新進程都擁有自己的內(nèi)存和數(shù)據(jù)棧,所以只能采用進程間通信(IPC)的方式共享信息。

    (2)線程與進程類似,不過他們是在同一個進程下執(zhí)行的,并共享相同的上下文。線程一般是以并發(fā)方式執(zhí)行的,但是在單核CPU中真正的并發(fā)是不可能的,:每個線程運行一小會兒,然后讓步給其他線(再次排隊等待更多的CPU時間)。但是,多線程訪問同一片數(shù)據(jù),由于訪問的順序不同可能導(dǎo)致結(jié)構(gòu)不一致。例如append(0-1)和print會同時有01

PS:內(nèi)存中可以有許多程序,但是在任意給定時刻只能有一個程序在運行。同理,盡管Python 解釋器中可以運行多個線程,但是在任意給定時刻只有一個線程會被解釋器執(zhí)行。

2.線程

    線程相關(guān)的模塊有thread和threading,其中threading是thread的改進和升級版,且thread模塊有一個致命的缺點,在主線程退出之后,所有其他線程都會在沒有清理的情況下直接退出。threading模塊中加入守護線程概念,如果被指明為守護線程后主線程退出后不會等待守護線程執(zhí)行完畢才吐出。整個Python 程序(可以解讀為:主線程)將在所有非守護線程退出之后才退出,換句話說,就是沒有剩下存活的非守護線程時。

主線程和子線程分別是什么?舉例?

     而主線程應(yīng)該做一個好的管理者,負責(zé)了解每個單獨的線程需要執(zhí)行什么,每個派生的線程需要哪些數(shù)據(jù)或參數(shù),這些線程執(zhí)行完成后會提供什么結(jié)果。這樣,主線程就可以收集每個線程的結(jié)果,然后匯總成一個有意義的最終結(jié)果。

(1)單線程:

  我需要做兩件事,只能做完一件再做第二件,排好隊

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# -*-coding:utf-8-*-
from time import ctime, sleep
import threading
loops = [4, 2]
def loop(nloop,nsec):
    print('start loop', nloop, 'at :', ctime())
    sleep(nsec)
    print('done loop', nloop, 'at:', ctime())
def main():
    print('start at',ctime())
    nloops = range(len(loops))
    for i in nloops:
        loop(i, loops[i])
    print('DONE AT:', ctime())
if __name__ == '__main__':
    main()

 返回結(jié)果:

start at Sun Dec 3 12:10:52 2017
start loop 0 at : Sun Dec 3 12:10:52 2017
done loop 0 at: Sun Dec 3 12:10:56 2017
start loop 1 at : Sun Dec 3 12:10:56 2017
done loop 1 at: Sun Dec 3 12:10:58 2017
DONE AT: Sun Dec 3 12:10:58 2017

(2) 多線程:(建立threads實例,傳給他一個函數(shù))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# -*-coding:utf-8-*-
from time import ctime, sleep
import threading
loops = [4, 2]
def loop(nloop,nsec):
    print('start loop', nloop, 'at :', ctime())
    sleep(nsec)
    print('done loop', nloop, 'at:', ctime())
def main():
    print('start at',ctime())
    threads = []
    nloops = range(len(loops))
    for i in nloops:
        t = threading.Thread(target=loop,args=(i,loops[i]))
        threads.append(t)
    for i in nloops:   # start threads 此處并不會執(zhí)行線程,而是將任務(wù)分發(fā)到每個線程,同步線程。等同步完成后再開始執(zhí)行start方法
        threads[i].start()
    for i in nloops:   # jion()方法等待線程完成
        threads[i].jion()
    print('DONE AT:', ctime())
if __name__ == '__main__':
    main()

運行結(jié)果:

start at Sun Dec 3 12:08:23 2017
start loop 0 at : Sun Dec 3 12:08:23 2017
start loop 1 at : Sun Dec 3 12:08:23 2017
done loop 1 at: Sun Dec 3 12:08:25 2017
done loop 0 at: Sun Dec 3 12:08:27 2017
DONE AT: Sun Dec 3 12:08:27 2017

可以看到loop0和loop1同時進行,當(dāng)時間較長的子線程loop0完成后,主線程print('DONE AT:', ctime())開始任務(wù)

(3)多線程(創(chuàng)建threads實例,傳遞給他一個可調(diào)用的類實例):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# -*-coding:utf-8-*-
from time import ctime, sleep
import threading
loops = [4, 2]
class MyThread(object):
    def __init__(self, func, args, name=''):
        self.name = name
        self.func = func
        self.args = args
    def __call__(self):
        self.func(*self.args)
def loop(nloop, nsec):
    print('start loop', nloop, 'at :', ctime())
    sleep(nsec)
    print('done loop', nloop, 'at:', ctime())
def main():
    print('start at',ctime())
    threads = []
    nloops = range(len(loops))
    for i in nloops:
        t = threading.Thread(target=MyThread(loop, (i, loops[i]), loop.__name__))
        threads.append(t)
    for i in nloops:   # start threads 此處并不會執(zhí)行線程,而是將任務(wù)分發(fā)到每個線程,同步線程。等同步完成后再開始執(zhí)行start方法
        threads[i].start()
    for i in nloops:   # jion()方法等待線程完成
        threads[i].join()
    print('DONE AT:', ctime())
if __name__ == '__main__':
    main()

join函數(shù)的原理就是一次檢驗線程池中的線程是否結(jié)束,沒有結(jié)束就阻塞直到線程結(jié)束。如果結(jié)束則就跳轉(zhuǎn)執(zhí)行下一個線程的join函數(shù)。如果不用join(),主線程跑的比子線程快會拿不到結(jié)果

(3)通過多線程獲取返回值

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# -*-coding:utf-8-*-
from time import ctime, sleep
import threading
import numpy as np
import collections
loops = ['廣州', '北京']
t_list = ['01', '02', '03']
cldas_sum = collections.deque()
class MyThread(threading.Thread):
    def __init__(self, func, args, name=''):
        threading.Thread.__init__(self)
        self.name = name
        self.func = func
        self.args = args
        self.result = self.func(*self.args)
    def get_result(self):
        try:
            return self.result
        except Exception:
            return None
def loop(nloop):
    for j in t_list:
        cldas_values = []
        for k in range(4):
            cldas_value = nloop + str(k)
            cldas_values.append(cldas_value)
        cldas_values.append(j)
        cldas_values.append(nloop)
        cldas_sum.append(cldas_values)
        print(id(cldas_values))
    #print(cldas_sum)
    return cldas_sum
def main():
    print('start at', ctime())
    threads = []
    nloops = range(len(loops))
    for i in nloops:
        t = MyThread(loop, (loops[i],), loop.__name__)
        threads.append(t)
    for i in nloops:   # start threads 此處并不會執(zhí)行線程,而是將任務(wù)分發(fā)到每個線程,同步線程。等同步完成后再開始執(zhí)行start方法
        threads[i].start()
    for i in nloops:   # jion()方法等待線程完成
        threads[i].join()
    print(threads[1].get_result())
    print('DONE AT:', ctime())
if __name__ == '__main__':
    main()

 

  寫這個腳本的一個目的就是看所有腳本共同調(diào)用同一個函數(shù),每個腳本都在這個函數(shù)中都有一個相同的變量,那么這個變量會被共用還是每個線程自己各有一個閉包。不過函數(shù)內(nèi)定義的變量是閉包,調(diào)用函數(shù)時創(chuàng)建,返回時銷毀。

最終返回結(jié)果如下:

start at Tue Dec 5 10:32:38 2017
728072411976
728072411848
728072411784
728072411656
728072364680
728072364808
deque([['廣州0', '廣州1', '廣州2', '廣州3', '01', '廣州'], ['廣州0', '廣州1', '廣州2', '廣州3', '02', '廣州'], ['廣州0', '廣州1', '廣州2', '廣州3', '03', '廣州'], ['北京0', '北京1', '北京2', '北京3', '01', '北京'], ['北京0', '北京1', '北京2', '北京3', '02', '北京'], ['北京0', '北京1', '北京2', '北京3', '03', '北京']])
DONE AT: Tue Dec 5 10:32:38 2017

 需要注意的是:

(1)如果多個線程共用一個公共數(shù)據(jù),那么我們需要做的就是將這個公共數(shù)據(jù)設(shè)置成隊列格式,要不然多個線程共同訪問這個數(shù)據(jù)可能會出錯,需要加鎖。設(shè)置成隊列比加鎖再放鎖效率高多了

(2)線程之間同一個變量id都不一樣,還是不知道是否其他線程會涉足另一個線程

 

 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約