Python スレッドをやってみる(2)

デーモンスレッドは、メインスレッドを含め、残っているスレッドがデーモンスレッドだけになった時、 Python プログラム全体を終了させる。
今回もTheading.Threadのコンストラクタに呼び出し可能オブジェクトを渡す形式でやってみる。そして懲りもせず、メモしておく。

  • デーモンスレッド
  • joinメソッドで、デーモンスレッドが終了するまで待つ
  • joinメソッドでタイムアウト引数を設定し、デーモンスレッドが終了するのを待たずにタイムアウトさせる
  • スレッドが複数起動していたとき、すべて終了するまでスレッドを監視する

デーモンスレッド

import threading

def DoSomething():
    for i in range(100):
        print i

if __name__=='__main__':
    t=threading.Thread(target=DoSomething)
    t.setDaemon(True)
    t.start()

メインスレッドがすぐ終了するので、デーモンスレッドだけになってしまい、プログラム全体がすぐ終了する。

0

デーモンスレッド メインスレッドで1秒スリープしてみる

import threading
import time

def DoSomething():
    for i in range(100):
        print i

if __name__=='__main__':
    t=threading.Thread(target=DoSomething)
    t.setDaemon(True)
    t.start()
    time.sleep(1)

メインスレッドがスリープしている間に、デーモンスレッドの実行がすべて終わった。そして、ちょっと間が開いてからプログラム全体が終了。うんうん、なるほど。

01
2
3
...
97
98
99

joinメソッドで、デーモンスレッドが終了するまで待ってみる

import threading

def DoSomething():
    for i in range(100):
        print i

if __name__=='__main__':
    t=threading.Thread(target=DoSomething)
    t.setDaemon(True)
    t.start()
    t.join()

スレッドを生成して、joinメソッドを呼んだので、メインスレッドがブロックされ、デーモンスレッドが終了するまで待つようになった。さっきのようにメインスレッドでスリープで長生きさせるより、結果はいっしょだけど、スマート。

01
2
3
...
97
98
99

joinメソッドでタイムアウト引数を設定し、デーモンスレッドが終了するのを待たずにタイムアウトさせる

import threading

def DoSomething():
    for i in range(10000):
        print i

if __name__=='__main__':
    t=threading.Thread(target=DoSomething)
    t.setDaemon(True)
    t.start()
    if t.isAlive():
        print "daemon is alive"
        t.join(0.01)

isAliveメソッドで、スレッドが生きているか確認し、生きていたらタイムアウト付きのjoinメソッドを呼んだ。10000までのカウント途中でスレッドが終了する。

0daemon is alive
1
2
3
4
5
6
7
8
9

スレッドが複数起動していたとき、すべて終了するまでスレッドを監視する

import threading
import time

def DoSomething(nsleep):
    for i in range(10):
        print "[%s]%d" % (threading.currentThread().getName(), i)
        time.sleep(nsleep)

if __name__=='__main__':
    t1=threading.Thread(target=DoSomething,name="thr1",args=(0.1,))
    t2=threading.Thread(target=DoSomething,name="thr2",args=(0.2,))
    t3=threading.Thread(target=DoSomething,name="thr3",args=(0.3,))
    t1.start()
    t2.start()
    t3.start()
    main_thread=threading.currentThread() 
    while True:
        tlist=threading.enumerate()
        if len(tlist) < 2: break
        for t in tlist:
            if t is main_thread: continue
            print t
        time.sleep(1)

threading.enumerateメソッドは稼動中のスレッドのリストを返す。メインスレッドも対象となるのでリストから取り除く。

[thr1]0
[thr2]0[thr3]0
<Thread(thr1, started 4880)>
<Thread(thr2, started 3616)>
<Thread(thr3, started 4392)>
[thr1]1
[thr2]1
[thr1]2
[thr3]1
[thr1]3
[thr2]2
[thr1]4
[thr1]5
[thr2]3
[thr3]2
[thr1]6
[thr1]7
[thr2]4
[thr1]8
[thr3]3
[thr1]9
<Thread(thr1, started 4880)>
<Thread(thr2, started 3616)>
<Thread(thr3, started 4392)>
[thr2]5
[thr2]6
[thr3]4
[thr2]7
[thr3]5
[thr2]8
[thr2]9
[thr3]6
<Thread(thr2, started 3616)>
<Thread(thr3, started 4392)>
[thr3]7
[thr3]8
[thr3]9
<Thread(thr3, started 4392)>