2013-02-08 110 views
7

我需要能够为当前正在运行的线程注入一些退出代码。我一直在努力与这一个了一段时间,我终于想出了一个解决方案在这里是一些代码类似于我在做什么:线程退出回调

public static void injectThreadExitCallback(final Runnable callback) { 
    final curr = Thread.currentThread(); 
    new Thread() { 
     @Override 
     public void run() { 
      try { 
       curr.join(); 
       callback.run(); 
      } catch (InterruptedException ex) { 
       ... logging ... 
      } 
     } 
    }.start(); 
} 

这似乎很好地工作和做我想要什么,我唯一担心的是,如果这导致任何泄漏或其他不良副作用,我可能不会看到。

或者这是非常好的,如果是这样,这是非常有用的。我可以看到一个简单的库,可以动态地将退出代码添加到现有的线程。

+1

看起来不错;请注意,回调将在单独的线程上运行。 – 2013-02-08 20:15:40

+1

将回调移动到'finally'块意味着如果'join'在目标线程退出之前抛出一个将会发生的异常,它就会运行。此外,除非某个外部代理开始中断所有线程,否则连接永远不会抛出异常。 – 2013-02-08 20:44:55

+0

如果您在此方法内创建的匿名线程中断,那么回调是否应该被调用是非常值得怀疑的。中断一个线程的目的是停止它正在做的事情。由于这个线程唯一做的就是等待调用回调函数,所以中断它的唯一原因就是阻止回调函数的运行。 – 2013-02-08 20:53:58

回答

3

您做的更好

new Thread() { 
    @Override 
    public void run() { 
     try 
     { 
      // Thread logic here 
     } 
     finally 
     { 
      // Thread exit logic here 
     } 
    } 
}.start(); 
+1

好点!这样,如果我包裹的线程死亡仍然会做我需要做的事情。 – 2013-02-08 20:14:03

+0

这不完全是注射,是吗?线程代码需要修改以合并线程退出逻辑。 (或者你是在谈论重组OP的建议行为注入线程? – 2013-02-08 20:17:07

+0

我认为他说我需要移动我的回调,以防例外情况,我想。 – 2013-02-08 20:19:09

0

您可以catch块之后或在final块移动callback.run();如果你想确保它反正叫

+0

一般来说,中断一个线程的唯一理由是让它停止正在做的事情。在这种情况下,它所做的唯一事情就是等待调用回调。因此,你确定不希望在线程中断时确保回调被调用! – 2013-02-08 21:35:56

+0

这是真的,但它取决于您希望确保调用'callback'或否的应用程序逻辑天气。例如,如果'callback'正在执行一些清理任务,即使线程中断,您也有合理的理由确保它被调用。 – iTech 2013-02-08 21:40:00

2

你不可能代码注入到一个除非该线程正在积极协作,例如AWT中的Event Dispatch Thread,它的根部有一个将Runnable从队列中取出并执行的循环。

您的设计可能会将数据竞争引入之前为单线程且因此没有并发问题的代码。最后,设计浪费了一个宝贵的系统资源(一个线程),除了等待另一个线程完成之外什么也不做。

如果您需要从外部修补一些现有的代码,那么它可能是唯一的选择;如果没有,最好为它提供一个更有效的明确机制。