加入Python

时间:2016-03-01 09:33:36

标签: python multithreading

我有一个带有一个主线程的python程序,让我们说2个其他线程(或者甚至更多,可能并不重要)。我想让主线程休眠直到其他一个线程完成。轮询很容易(通过调用t.join(1)并为每个线程t等待一秒钟)。

是否可以在没有轮询的情况下进行,仅通过

SOMETHING_LIKE_JOIN(1, [t1, t2])

其中t1和t2是线程。线程对象?呼叫必须执行以下操作:休眠1秒,但只要t1,t2中的一个完成就唤醒。与使用两个文件描述符的POSIX select(2)调用非常类似。

3 个答案:

答案 0 :(得分:2)

一种解决方案是使用multiprocessing.dummy.Pool; multiprocessing.dummy提供的API几乎与multiprocessing相同,但由线程支持,因此它可以免费获得一个线程池。

例如,你可以这样做:

from multiprocessing.dummy import Pool as ThreadPool

pool = ThreadPool(2)  # Two workers
for res in pool.imap_unordered(some_func, list_of_func_args):
    # res is whatever some_func returned

multiprocessing.Pool.imap_unordered会在结果可用时返回结果,无论哪个任务首先完成。

如果您可以使用Python 3.2或更高版本(或为旧版Python安装concurrent.futures PyPI模块),您可以通过从{{1}创建一个或多个Future来概括为不同的任务函数},然后将concurrent.futures.waitThreadPoolExecutor一起使用,或使用return_when=FIRST_COMPLETED获得类似效果。

答案 1 :(得分:1)

以下是使用条件对象的示例。

from threading import Thread, Condition, Lock
from time import sleep
from random import random


_lock = Lock()


def run(idx, condition):
    sleep(random() * 3)
    print('thread_%d is waiting for notifying main thread.' % idx)
    _lock.acquire()
    with condition:
        print('thread_%d notifies main thread.' % idx)
        condition.notify()


def is_working(thread_list):
    for t in thread_list:
        if t.is_alive():
            return True
    return False


def main():
    condition = Condition(Lock())
    thread_list = [Thread(target=run, kwargs={'idx': i, 'condition': condition}) for i in range(10)]

    with condition:
        with _lock:
            for t in thread_list:
                t.start()

            while is_working(thread_list):
                _lock.release()
                if condition.wait(timeout=1):
                    print('do something')
                    sleep(1)  # <-- Main thread is doing something.
                else:
                    print('timeout')

    for t in thread_list:
        t.join()


if __name__ == '__main__':
    main()

我不认为你在评论中描述了竞争条件。条件对象包含一个锁。当主线程工作时(示例中为sleep(1)),它保持锁定,没有线程可以通知它,直到它完成其工作并释放锁定。

我只是意识到上一个例子中存在竞争条件。我添加了一个全局_lock,以确保在主线程开始等待之前,条件永远不会通知主线程。我不喜欢它是如何工作的,但我还没有想出更好的解决方案......

答案 2 :(得分:-1)

您可以创建一个Thread类,主线程会保留对它的引用。因此,您可以检查线程是否已完成,并使主线程再次轻松继续。

如果这对您没有帮助,我建议您查看队列库!

import threading
import time, random


#THREAD CLASS#
class Thread(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)

        self.daemon = True
        self.state = False

        #START THREAD (THE RUN METHODE)#
        self.start()

    #THAT IS WHAT THE THREAD ACTUALLY DOES#
    def run(self):

        #THREAD SLEEPS FOR A RANDOM TIME RANGE# 
        time.sleep(random.randrange(5, 10))

        #AFTERWARDS IS HAS FINISHED (STORE IN VARIABLE)#
        self.state = True


    #RETURNS THE STATE#
    def getState(self):

        return self.state


#10 SEPERATE THREADS#
threads = []

for i in range(10):
    threads.append(Thread())

#MAIN THREAD#
while True:

    #RUN THROUGH ALL THREADS AND CHECK FOR ITS STATE#
    for i in range(len(threads)):
        if threads[i].getState():
            print "WAITING IS OVER: THREAD ", i 

    #SLEEPS ONE SECOND#
    time.sleep(1)