2017-08-01 66 views
0

難道有人請澄清爲什麼這個線程代碼調用類的方法永遠不會完成?在python線程隊列中調用類方法

from Queue import Queue 
from threading import Thread 

class SimpleThing(object): 
    def __init__(self, name): 
     self.name = name 

    def print_name(self): 
     print self.name 

class ThingSpawner(object): 
    def __init__(self, name_list): 
     self.things = [SimpleThing(name) for name in name_list] 
     self.thread_queue = Queue() 

    def run(self): 
     for thing in self.things: 
      t = Thread(target=thing.print_name, name=thing.name) 
      t.daemon = True 
      t.start() 
      self.thread_queue.put(t) 
     self.thread_queue.join() 

thing_list = ['cat', 'dog', 'llama', 'bat'] 

sp = ThingSpawner(thing_list) 
sp.run() 

代碼將明確運行print_name方法,但不join()並退出。

此外,什麼是最好的方式來修改此代碼,以便join()完成?動機是使用現有的python控件類來實現一些硬件,並允許您並行調用控件類的(非常慢)方法。謝謝!

回答

1

當你在做

self.thread_queue.put(t) 

你是把一些線程進入Queue,效果顯着。但是,我不確定爲什麼。你再也不用這個隊列來完成任何事情,這是完全沒有必要的。更糟糕的是,你再調用

self.thread_queue.join() 

這基本上將永遠等待隊列空,這不會發生,因爲你永遠不空或用它做任何事情。

如果我複製粘貼所有的代碼,但沒有任何Queue可言,一切都很好...

from threading import Thread 

class SimpleThing(object): 
    def __init__(self, name): 
     self.name = name 

    def print_name(self): 
     print self.name 

class ThingSpawner(object): 
    def __init__(self, name_list): 
     self.things = [SimpleThing(name) for name in name_list] 

    def run(self): 
     for thing in self.things: 
      t = Thread(target=thing.print_name, name=thing.name) 
      t.daemon = True 
      t.start() 

thing_list = ['cat', 'dog', 'llama', 'bat'] 

sp = ThingSpawner(thing_list) 
sp.run() 

然而,這不是你想要的!因爲你的線程是守護進程,它們將在主程序退出時退出,即使它們尚未完成(如果在打印名稱之前添加了一些延遲,例如sleep(1))。如果你想等待它們完成,你應該在線程上調用join(),而不是隊列。因此,我們將首先返回線程:

def run(self): 
     all_threads = [] 
     for thing in self.things: 
      t = Thread(target=thing.print_name, name=thing.name) 
      t.daemon = True 
      t.start() 
      all_threads.append(t) 
     return all_threads 

當我們run我們將做到這一點:爲明確的答案,這是我剛剛接受了

threads = sp.run() 
for t in threads: 
    t.join() 
0

感謝奧弗 - 我確實沒有正確使用隊列!已經重新認識自己與隊列現在你指出我的錯誤,繁榮,這裏是一個使用隊列的替代方法:一旦我明白我的錯誤

from Queue import Queue 
from threading import Thread 

class SimpleThing(object): 
    def __init__(self, name, q): 
     self.name = name 

    def print_name(self, q): 
     print self.name 
     q.get() 
     q.task_done() 

class ThingSpawner(object): 
    def __init__(self, name_list): 
     self.thread_queue = Queue() 
     self.things = [SimpleThing(name, self.thread_queue) for name in name_list] 


    def run(self): 
     for thing in self.things: 
      t = Thread(target=thing.print_name, name=thing.name, args=(self.thread_queue,)) 
      t.daemon = True 
      t.start() 
      self.thread_queue.put(t) 
     self.thread_queue.join() 

thing_list = ['cat', 'dog', 'llama', 'bat'] 

sp = ThingSpawner(thing_list) 
sp.run() 

This tutorial穿線和隊列是有益的。