2016-01-02 25 views
5

我想在一个线程(它正在遍历大型数据库表)中运行一个进程。线程运行时,我只想让程序等待。如果该线程需要30秒以上,我想杀死线程并执行其他操作。通过杀死线程,我的意思是我希望它停止活动并优雅地释放资源。大部分Pythonic方法在一段时间后杀死线程

我想通做的最好的方式,这是通过Thread()join(delay)is_alive()功能,以及Event。使用join(delay)我可以让我的程序等待30秒以完成线程,通过使用is_alive()函数,我可以确定线程是否已完成其工作。如果尚未完成其工作,则会设置该事件,并且该线程知道在该点停止工作。

是这种方法有效,这是去我的问题语句的最Python的方式?

下面是一些示例代码:

import threading 
import time 

# The worker loops for about 1 minute adding numbers to a set 
# unless the event is set, at which point it breaks the loop and terminates 
def worker(e): 
    data = set() 
    for i in range(60): 
     data.add(i) 
     if not e.isSet(): 
      print "foo" 
      time.sleep(1) 
     else: 
      print "bar" 
      break 

e = threading.Event() 
t = threading.Thread(target=worker, args=(e,)) 
t.start() 

# wait 30 seconds for the thread to finish its work 
t.join(30) 
if t.is_alive(): 
    print "thread is not done, setting event to kill thread." 
    e.set() 
else: 
    print "thread has already finished." 

回答

2

使用在这种情况下,事件是作品只是罚款作为信令机制, 在threading module docs实际建议。

如果你想你的线程停止摆好,让他们非邪,并使用 合适的信令机制,如Event

在验证线程终止时,超时几乎总会为 错误引入空间。因此,在初始 决定触发事件时使用.join()时,如果使用.join()为准,则应使用 .join()进行最终验证而不超时。

# wait 30 seconds for the thread to finish its work 
t.join(30) 
if t.is_alive(): 
    print "thread is not done, setting event to kill thread." 
    e.set() 
    # The thread can still be running at this point. For example, if the 
    # thread's call to isSet() returns right before this call to set(), then 
    # the thread will still perform the full 1 second sleep and the rest of 
    # the loop before finally stopping. 
else: 
    print "thread has already finished." 

# Thread can still be alive at this point. Do another join without a timeout 
# to verify thread shutdown. 
t.join() 

这可以简化为这样的事:

# Wait for at most 30 seconds for the thread to complete. 
t.join(30) 

# Always signal the event. Whether the thread has already finished or not, 
# the result will be the same. 
e.set() 

# Now join without a timeout knowing that the thread is either already 
# finished or will finish "soon." 
t.join()