如果访问了两个线程,但是当它们一起执行时,halt_listener
将独占不允许import_1
执行的资源。最终目标是让halt_listener侦听kill消息,然后将run变量设置为false。当我向halt_listener发送管道时,这有用,但我更喜欢队列。
这是我的代码:
import multiprocessing
import time
from threading import Thread
class test_imports:#Test classes remove
alive = {'import_1': True, 'import_2': True};
def halt_listener(self, control_Queue, thread_Name, kill_command):
while True:
print ("Checking queue for kill")
isAlive = control_queue.get()
print ("isAlive", isAlive)
if isAlive == kill_command:
print ("kill listener triggered")
self.alive[thread_Name] = False;
return
def import_1(self, control_Queue, thread_Number):
print ("Import_1 number %d started") % thread_Number
halt = test_imports()
t = Thread(target=halt.halt_listener, args=(control_Queue, 'import_1', 't1kill'))
count = 0
t.run()
global alive
run = test_imports.alive['import_1'];
while run:
print ("Thread type 1 number %d run count %d") % (thread_Number, count)
count = count + 1
print ("Test Import_1 ", run)
run = self.alive['import_1'];
print ("Killing thread type 1 number %d") % thread_Number
我错过了什么吗?
答案 0 :(得分:5)
问题在于您正在呼叫t.run()
。 run
不是启动线程的方法; run
是要在线程上运行的实际代码。通过直接调用它,您可以在 线程上运行它,并等待它完成。
你想要的是t.start()
。
有关详细信息,请参阅threading.Thread
上的文档。
虽然我们处于此状态,但您的代码还存在其他一些问题。
首先,你没有锁定self.alive
。您不能在一个线程中更改值(除了少量自动自同步类型,如Queue
),而在没有锁定的情况下在另一个线程中访问它。你经常可以逃脱它,但是在多线程程序中“经常”只是意味着它在你的大型演示之前不会失败,然后在你甚至可以开始修复它之前需要花费数周的时间来弄清楚如何再现......(In在这种情况下,条件可能比Lock更有意义,但无论哪种方式,您都需要在某事上进行同步。)
与此同时,尽可能快地循环轮询self.alive['import_1']
将无缘无故地燃烧100%的CPU。几乎总有一种更好的方法可以等待某些事情(例如,在这种情况下,如果您使用条件进行同步,您也可以使用它在这里等待);在极少数情况下,如果没有,每次循环时至少应sleep
。
alive
实际上是一个类属性而不是实例属性。这通常不是你想要的。实际上,您尝试同时访问test_imports.alive
和self.alive
,但只要您从未分配给它们,这两者都将成为类属性,这会使其更加混乱。然后,最重要的是,你有一个同名的全局,这只是极度困惑的一个秘诀。
此外,这看起来像Python 2代码,但您使用print
就好像它在某些情况下是一个函数 - 例如print ("isAlive", isAlive)
。这不会做你想要的 - 而不是打印像isAlive command
这样的东西,它会打印像('isAlive', 'command')
这样的东西,这不是很漂亮。同时,像("Import_1 number %d started") % thread_Number
这样的表达式中的额外括号意味着有人必须多次阅读,以说服自己括号实际上没有做任何事情。
最后,为什么要创建一个单独的test_imports
实例来调用halt_listener
?显然,这两种方法试图通过self
上的属性进行通信,但如果它们被调用在两个不同的对象上,它们就不会这样做。为什么不只是target=self.half_listener
?