263

私はPythonのスレッド化を研究していて、出会いましjoin()た.

作者は、スレッドがデーモンモードの場合、join()メインスレッドが終了する前にスレッドが終了できるように使用する必要があると言いました。

しかし、私は彼がそうではなかったt.join()としても使用しているのを見てきましたtdaemon

サンプルコードはこれです

import threading
import time
import logging

logging.basicConfig(level=logging.DEBUG,
                    format='(%(threadName)-10s) %(message)s',
                    )

def daemon():
    logging.debug('Starting')
    time.sleep(2)
    logging.debug('Exiting')

d = threading.Thread(name='daemon', target=daemon)
d.setDaemon(True)

def non_daemon():
    logging.debug('Starting')
    logging.debug('Exiting')

t = threading.Thread(name='non-daemon', target=non_daemon)

d.start()
t.start()

d.join()
t.join()

t.join()デーモンではなく、削除しても変化が見られないため、何を使用しているのかわかりません

4

10 に答える 10

355

メカニズムを示すためのやや不器用なアスキーアート:join()おそらくメインスレッドによって呼び出されます。別のスレッドから呼び出すこともできますが、図が不必要に複雑になります。

join-calling はメイン スレッドのトラックに配置する必要がありますが、スレッド関係を表現し、できるだけシンプルに保つために、代わりに子スレッドに配置することにしました。

without join:
+---+---+------------------                     main-thread
    |   |
    |   +...........                            child-thread(short)
    +..................................         child-thread(long)

with join
+---+---+------------------***********+###      main-thread
    |   |                             |
    |   +...........join()            |         child-thread(short)
    +......................join()......         child-thread(long)

with join and daemon thread
+-+--+---+------------------***********+###     parent-thread
  |  |   |                             |
  |  |   +...........join()            |        child-thread(short)
  |  +......................join()......        child-thread(long)
  +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,     child-thread(long + daemonized)

'-' main-thread/parent-thread/main-program execution
'.' child-thread execution
'#' optional parent-thread execution after join()-blocked parent-thread could 
    continue
'*' main-thread 'sleeping' in join-method, waiting for child-thread to finish
',' daemonized thread - 'ignores' lifetime of other threads;
    terminates when main-programs exits; is normally meant for 
    join-independent tasks

したがって、変更が表示されない理由は、メインスレッドが の後に何もしないためですjoinjoinメインスレッドの実行フローに(のみ)関連していると言えます。

たとえば、多数のページを同時にダウンロードしてそれらを 1 つの大きなページに連結する場合、スレッドを使用して同時ダウンロードを開始できますが、最後のページ/スレッドが終了するまで待ってから単一ページの組み立てを開始する必要があります。多くのうち。そんな時は を使いますjoin()

于 2013-02-26T10:00:20.560 に答える
85

ドキュメントから直接

join([timeout]) スレッドが終了するまで待ちます。これにより、join() メソッドが呼び出されたスレッドが終了するまで (通常または未処理の例外によって)、またはオプションのタイムアウトが発生するまで、呼び出し元のスレッドがブロックされます。

これは、生成されたメインスレッドがt終了するまでd待機することを意味します。t

プログラムが採用しているロジックによっては、スレッドが終了するまで待ってからメイン スレッドを続行したい場合があります。

また、ドキュメントから:

スレッドは「デーモンスレッド」としてフラグを立てることができます。このフラグの意味は、デーモン スレッドだけが残ったときに Python プログラム全体が終了することです。

簡単な例として、これがあるとします:

def non_daemon():
    time.sleep(5)
    print 'Test non-daemon'

t = threading.Thread(name='non-daemon', target=non_daemon)

t.start()

次で終了します。

print 'Test one'
t.join()
print 'Test two'

これは以下を出力します:

Test one
Test non-daemon
Test two

ここで、マスター スレッドは、2 回目tに呼び出すまで、スレッドが終了するのを明示的に待機しますprint

あるいは、これがあった場合:

print 'Test one'
print 'Test two'
t.join()

次の出力が得られます。

Test one
Test two
Test non-daemon

ここでは、メイン スレッドでジョブを実行し、tスレッドが終了するのを待ちます。この場合、明示的な結合t.join()を削除することもでき、プログラムは暗黙的tに終了を待ちます。

于 2013-02-26T09:31:12.417 に答える
51

このスレッドをありがとう - 私も大いに役立ちました。

今日は .join() について学びました。

これらのスレッドは並行して実行されます。

d.start()
t.start()
d.join()
t.join()

これらは順番に実行されます(私が望んでいたものではありません):

d.start()
d.join()
t.start()
t.join()

特に、私は賢く整頓しようとしていました:

class Kiki(threading.Thread):
    def __init__(self, time):
        super(Kiki, self).__init__()
        self.time = time
        self.start()
        self.join()

これはうまくいきます!しかし、それは順次実行されます。self.start() を __ init __ に入れることはできますが、self.join() を入れることはできません。これは、すべてのスレッドが開始された後に行う必要があります。

join() は、スレッドが終了するまでメインスレッドを待機させるものです。それ以外の場合、スレッドはすべて単独で実行されます。

したがって、join() をメイン スレッドの "保留" と考える 1 つの方法は、メイン スレッドが続行できるようになる前に、スレッドをスレッド化解除し、メイン スレッドで順次実行することです。メインスレッドが進む前にスレッドが完了することを保証します。これは、join() を呼び出す前にスレッドが既に終了していても問題ないことを意味することに注意してください。メイン スレッドは、join() が呼び出されるとすぐに解放されます。

実際、スレッド d が終了するまでメイン スレッドが d.join() で待機してから、t.join() に移動することが今思い浮かびました。

実際、非常に明確にするために、次のコードを検討してください。

import threading
import time

class Kiki(threading.Thread):
    def __init__(self, time):
        super(Kiki, self).__init__()
        self.time = time
        self.start()

    def run(self):
        print self.time, " seconds start!"
        for i in range(0,self.time):
            time.sleep(1)
            print "1 sec of ", self.time
        print self.time, " seconds finished!"


t1 = Kiki(3)
t2 = Kiki(2)
t3 = Kiki(1)
t1.join()
print "t1.join() finished"
t2.join()
print "t2.join() finished"
t3.join()
print "t3.join() finished"

この出力が生成されます (print ステートメントが互いにスレッド化されていることに注意してください)。

$ python test_thread.py
32   seconds start! seconds start!1

 seconds start!
1 sec of  1
 1 sec of 1  seconds finished!
 21 sec of
3
1 sec of  3
1 sec of  2
2  seconds finished!
1 sec of  3
3  seconds finished!
t1.join() finished
t2.join() finished
t3.join() finished
$ 

t1.join() がメイン スレッドを停止しています。3 つのスレッドはすべて t1.join() が終了する前に完了し、メイン スレッドは印刷、t2.join()、印刷、t3.join()、印刷の順に実行されます。

訂正歓迎。私はスレッド化も初めてです。

(注: ご参考までに、私は DrinkBot のコードを書いています。材料ポンプを順次ではなく同時に実行するためにスレッド化が必要です。各ドリンクを待つ時間が短縮されます。)

于 2016-05-20T04:25:55.540 に答える
21

メソッド join()

join() メソッドが呼び出されたスレッドが終了するまで、呼び出しスレッドをブロックします。

ソース: http://docs.python.org/2/library/threading.html

于 2013-02-26T09:30:59.273 に答える
-3

「join() を使用する用途は何ですか?」あなたは言う。本当に、それは「私のプログラムが終了すると、PythonとOSが私のファイルを閉じてくれるので、ファイルを閉じることの用途は何ですか?」と同じ答えです。

それは単に良いプログラミングの問題です。自分のコードに干渉するためにスレッドが実行されていないことを確実にする必要があるため、またはスレッドで正しく動作する必要があるため、コード内でスレッドが実行されるべきではない時点でスレッドを join() する必要があります。より大きなシステム。

join() に追加の時間が必要になる可能性があるという理由だけで、「コードの応答を遅らせたくない」と言うかもしれません。これはいくつかのシナリオでは完全に有効かもしれませんが、コードが「python と OS がクリーンアップするために残骸を残している」ことを考慮する必要があります。パフォーマンス上の理由でこれを行う場合は、その動作を文書化することを強くお勧めします。これは、他の人が利用することが期待されるライブラリ/パッケージを構築している場合に特に当てはまります。

パフォーマンス上の理由以外に、join() を使用しない理由はありません。あなたのコードがそれほどうまく機能する必要はないと私は主張します

于 2013-12-19T23:05:19.807 に答える