11

いくつかのスレッドを生成するPythonプログラムがあります。これらのスレッドは2秒から30秒の間どこでも続きます。メインスレッドでは、各スレッドが完了してメッセージを出力するたびに追跡したいと思います。すべてのスレッドを順番に.join()し、最初のスレッドが30秒続き、他のスレッドがもっと早く完了すると、メッセージを早く印刷できなくなります。すべてのメッセージは30秒後に印刷されます。

基本的に、スレッドが完了するまでブロックしたいと思います。スレッドが完了するとすぐに、そのスレッドに関するメッセージを出力し、他のスレッドがまだ生きている場合はブロックに戻ります。すべてのスレッドが完了したら、プログラムを終了します。

私が考えることができる1つの方法は、すべてのスレッドに渡され、queue.get()でブロックされるキューを持つことです。キューからメッセージを受信するたびに、メッセージを出力し、threading.active_count()を使用して他のスレッドが稼働しているかどうかを確認し、稼働している場合は、queue.get()のブロックに戻ります。これは機能しますが、ここではすべてのスレッドが終了する前にキューにメッセージを送信するという規律に従う必要があります。

これがこの振る舞いを達成するための従来の方法なのか、それとも他の/より良い方法があるのだろうか?

4

7 に答える 7

7

これは@detlyの回答のバリエーションであり、ターゲット関数からメッセージを出力する代わりに、メインスレッドからメッセージを指定できます。これにより、ターゲットを呼び出し、終了する前にメッセージを出力するラッパー関数が作成されます。これを変更して、各スレッドが完了した後に任意の種類の標準クリーンアップを実行できます。

#!/usr/bin/python

import threading
import time

def target1():
    time.sleep(0.1)
    print "target1 running"
    time.sleep(4)

def target2():
    time.sleep(0.1)
    print "target2 running"
    time.sleep(2)

def launch_thread_with_message(target, message, args=[], kwargs={}):
    def target_with_msg(*args, **kwargs):
        target(*args, **kwargs)
        print message
    thread = threading.Thread(target=target_with_msg, args=args, kwargs=kwargs)
    thread.start()
    return thread

if __name__ == '__main__':
    thread1 = launch_thread_with_message(target1, "finished target1")
    thread2 = launch_thread_with_message(target2, "finished target2")

    print "main: launched all threads"

    thread1.join()
    thread2.join()

    print "main: finished all threads"
于 2015-09-04T19:00:32.037 に答える
6

呼び出しを使用してスレッドをチェックする必要がありますThread.is_alive()

于 2012-05-03T23:33:28.460 に答える
4

スレッド自体に完了メッセージを出力させたり、完了時に他の完了コールバックを呼び出したりしないのはなぜですか?

メインプログラムからこれらのスレッドだけを取得できるjoinため、一連の完了メッセージが表示され、必要に応じて、すべてが完了するとプログラムが終了します。

すばやく簡単なデモンストレーションを次に示します。

#!/usr/bin/python

import threading
import time

def really_simple_callback(message):
    """
    This is a really simple callback. `sys.stdout` already has a lock built-in,
    so this is fine to do.
    """    
    print message

def threaded_target(sleeptime, callback):
    """
    Target for the threads: sleep and call back with completion message.
    """
    time.sleep(sleeptime)
    callback("%s completed!" % threading.current_thread())

if __name__ == '__main__':
    # Keep track of the threads we create
    threads = []

    # callback_when_done is effectively a function
    callback_when_done = really_simple_callback

    for idx in xrange(0, 10):
        threads.append(
            threading.Thread(
                target=threaded_target,
                name="Thread #%d" % idx,
                args=(10 - idx, callback_when_done)
            )
        )

    [t.start() for t in threads]
    [t.join() for t in threads]

    # Note that thread #0 runs for the longest, but we'll see its message first!
于 2012-05-04T00:32:06.960 に答える
2

私が提案するのは、このようなループです

while len(threadSet) > 0:
    time.sleep(1)
    for thread in theadSet:
        if not thread.isAlive()
            print "Thread "+thread.getName()+" terminated"
            threadSet.remove(thread)

1秒間のスリープがあるため、スレッドの終了とメッセージの印刷の間にわずかな遅延が発生します。この遅れに耐えられるのであれば、これはあなたが質問で提案したものよりも簡単な解決策だと思います。

于 2012-05-04T00:22:10.290 に答える
1

スレッドに結果をにプッシュさせることができますthreading.Queue。このキューで別のスレッドを待機させ、新しいアイテムが表示されたらすぐにメッセージを出力します。

于 2012-05-03T23:29:58.277 に答える
0

使用に問題があるかどうかわかりません:threading.activeCount()

まだアクティブなスレッドの数を追跡するには?

開始する前に起動するスレッドの数がわからなくても、追跡するのは非常に簡単なようです。私は通常、リスト内包表記を使用してスレッドコレクションを生成します。次に、activeCountを使用してリストサイズと単純に比較すると、終了した数がわかります。

ここを参照してください:http://docs.python.org/library/threading.html

または、スレッドオブジェクトを取得したら、スレッドオブジェクト内で.isAliveメソッドを使用して確認することもできます。

私はこれを私が持っているマルチスレッドプログラムに投げ込むことによってチェックしました、そしてそれはうまく見えます:

for thread in threadlist:
        print(thread.isAlive())

スレッドのオンとオフが切り替わるときに、True/Falseのリストが表示されます。したがって、スレッドが終了したかどうかを確認するために、それを実行してFalseをチェックできるはずです。

于 2012-05-03T23:29:51.157 に答える
0

アプリケーションで使用したスレッドの性質上、少し異なる手法を使用します。説明のために、これは、スレッドクラスのバリアクラスをスキャフォールディングするために作成したテストストラッププログラムのフラグメントです。

   while threads:
        finished = set(threads) - set(threading.enumerate())
        while finished:
            ttt = finished.pop()
            threads.remove(ttt)
        time.sleep(0.5)

なぜ私はそれをこのようにするのですか?私の本番コードには時間制限があるので、最初の行は実際には「whileスレッドとtime.time()<cutoff_time」と表示されます。カットオフに達すると、スレッドにシャットダウンするように指示するコードがあります。

于 2016-09-08T14:55:18.810 に答える