2014-12-23 25 views
0

我是新來的線程在python中,我有一個問題,應該我開始像下面這樣的3個線程,每個人都需要照顧1個不同的任務:python會不同的線程在第一個完成的同時結束

def start(taskName, delay): 
    // do somthing with each taskName 

# Create two threads as follows 
try: 
    thread.start_new_thread(start, ("task1",)) 
    thread.start_new_thread(start, ("task2",)) 
    thread.start_new_thread(start, ("task3",)) 
except: 
    print "Error: unable to start thread" 

假設每個「啓動」,它需要約10-15秒,這取決於每個TASKNAME它完成。我的問題是,如果任務1在12秒內完成,則10秒內的任務2和15秒內的任務3。任務2完成後關閉,任務1和任務3運行結束,或任務2完成任務2後強制任務1和3關閉?

是否有任何參數可以傳遞給start_new_thread方法以存檔上面提到的兩件事: 1.首先完成,強制其餘的關閉。 2.每人單獨完成。

謝謝

回答

1

正如馬克斯諾埃爾已經提到的,建議使用線程類而不是使用start_new_thread。

現在,爲您的兩個問題:

1.首先完成強制休息,關閉 您將需要兩個重要的事情:共享隊列,該線程可以把自己的ID中,一旦他們完成。還有一個共享事件,它會在所有線程觸發時停止工作。主線程將等待第一個線程將某些東西放入隊列中,然後觸發事件停止所有線程。

import threading 
import random 
import time 
import Queue 

def work(worker_queue, id, stop_event): 
    while not stop_event.is_set(): 
     print "This is worker", id 

     # do stuff 
     time.sleep(random.random() * 5) 

     # put worker ID in queue 
     if not stop_event.is_set(): 
      worker_queue.put(id) 

     break 

# queue for workers 
worker_queue = Queue.Queue() 

# indicator for other threads to stop 
stop_event = threading.Event() 

# run workers 
threads = [] 
threads.append(threading.Thread(target=work, args=(worker_queue, 0, stop_event))) 
threads.append(threading.Thread(target=work, args=(worker_queue, 1, stop_event))) 
threads.append(threading.Thread(target=work, args=(worker_queue, 2, stop_event))) 

for thread in threads: 
    thread.start() 

# this will block until the first element is in the queue 
first_finished = worker_queue.get() 

print first_finished, 'was first!' 

# signal the rest to stop working 
stop_event.set() 

2.每個單獨完成 現在,這是容易得多。只需在所有線程對象上調用join方法即可。這將等待每個線程完成。

for thread in threads: 
    thread.start() 

for thread in threads: 
    thread.join() 

順便說一下,上面的代碼是針對Python 2.7的。讓我知道如果你需要Python 3

+0

非常豐富和適用於即時通訊工作,謝謝。爲了您對號碼2的回答,是否需要調用thread.start()?開始和加入有什麼區別? – Kiddo

+0

開始將啓動線程。加入將等待線程完成 - 它不會啓動它 –

+0

因此對於循環中的2 /我們必須同時加入()和開始()才能工作,這是正確的嗎? – Kiddo

1

首先,不使用start_new_thread,這是一個低級別的原語。相反,請使用threading模塊中的Thread類。

一旦你有了這個,Thread實例有一個.join()方法,你可以從另一個線程(你的程序的主線程)調用它來等待它們終止。

t1 = Thread(target=my_func) 
t1.start() 
# Waits for t1 to finish. 
t1.join() 
+0

感謝您指出這一點! – Kiddo

0

當進程終止時,所有線程都會終止。因此,如果您的主程序在try..except之後結束,則所有三個線程可能會提前終止。例如:

import thread 
import logging 
import time 
logger = logging.getLogger(__name__) 

def start(taskname, n): 
    for i in range(n): 
     logger.info('{}'.format(i)) 
     time.sleep(0.1) 

if __name__ == '__main__': 
    logging.basicConfig(level=logging.DEBUG, 
         format='[%(asctime)s %(threadName)s] %(message)s', 
         datefmt='%H:%M:%S') 
    try: 
     thread.start_new_thread(start, ("task1", 10)) 
     thread.start_new_thread(start, ("task2", 5)) 
     thread.start_new_thread(start, ("task3", 8)) 
    except Exception as err: 
     logger.exception(err) 

可以打印出類似這樣

[14:15:16 Dummy-3] 0 
[14:15:16 Dummy-1] 0 

相反,如果你把

time.sleep(5) 

在腳本的末尾,那麼你看到所有的充分預期輸出三個 線程。


還要注意,線程模塊是低級模塊;除非你有使用它的特殊原因,否則大多數人通常使用線程模塊,它可以實現更多有用的線程處理功能,例如在線程完成之前會阻塞的方法,如join 。見下面的例子。


The docs state

當函數返回時,線程自行退出。 當函數以未處理的異常終止時,將打印一個堆棧跟蹤 ,然後該線程退出(,但其他線程繼續運行)。

因此,默認情況下,當一個線程完成時,其他線程繼續運行。 上面的例子也證明了這一點。


使一個函數完成時所有線程退出更困難。 一個線程不能殺死另一個線程乾淨(例如,而不殺死整個 過程。)使用threading

,你可以安排線程設置一個變量 (如flag)爲True時結束,並有各線程定期檢查 flag的狀態,如果它爲True,則退出。但請注意,其他線程 不一定終止立即;他們只會在他們下一次 檢查flag的狀態時終止。如果線程被阻塞,例如等待I/O,則 然後它可能不檢查flag相當長的時間(如果有的話!)。

但是,如果線程大部分時間處於一個快速循環,你可以檢查每次迭代一次flag狀態:

import threading 
import logging 
import time 
logger = logging.getLogger(__name__) 

def start(taskname, n): 
    global flag 
    for i in range(n): 
     if flag: 
      break 
     logger.info('{}'.format(i)) 
     time.sleep(0.1) 
    else: 
     # get here if loop finishes without breaking 
     logger.info('FINISHED') 
    flag = True 

if __name__ == '__main__': 
    logging.basicConfig(level=logging.DEBUG, 
         format='[%(asctime)s %(threadName)s] %(message)s', 
         datefmt='%H:%M:%S') 
    threads = list() 
    flag = False 
    try: 
     threads.append(threading.Thread(target=start, args=("task1", 10))) 
     threads.append(threading.Thread(target=start, args=("task2", 5))) 
     threads.append(threading.Thread(target=start, args=("task3", 8))) 
    except Exception as err: 
     logger.exception(err) 

    for t in threads: 
     t.start() 
    for t in threads: 
     # make the main process wait until all threads have finished. 
     t.join()  
+0

非常豐富,謝謝 – Kiddo

相關問題