【问题标题】:What is the preferred way to use interrupt a Java Runnable and run clean up?使用中断 Java Runnable 并运行清理的首选方法是什么?
【发布时间】:2015-03-09 21:21:47
【问题描述】:

这里有关于设计的一般问题。我有一些线程需要在后台保持运行,基本上是一些数据库上传/故障处理任务。都具有以下流模式:

public class Worker implements Runnable {
    private AtomicBoolean isAlive = new AtomicBoolean(true);
    ....
    public void run() {
        while (isAlive.get()) {

            // do some work here, slightly heavy

            if (Thread.interrupted()) {
                // checking Thread.interrupted() as the code above
                // can take a while and interrupt may happen before 
                // it gets here.
                isAlive.setBoolean(false);
                break; // to exit faster
            }

            try { Thread.sleep(sleepTime); } 
            catch (InterruptedException e) {
                isAlive.setBoolean(false);
                break; // to exit faster
            }
        }

        cleanUp(); // e.g. close db connections etc
     }
}

现在我希望能够中断线程,以便它可以优雅地跳出 while 循环并运行 cleanUp() 方法。

有很多方法可以做到这一点,这里列举几个:

  1. Threads 中关闭Runnables,然后使用interrupt() 方法:

    List<Thread> threadList =...
    for (int i < 0; i < threadCount; i++) {
        Thread t = new Thread(new Worker());
        threadList.add(t);
        t.start()
    }
    
    // later
    for (Thread t : threadList) { t.interrupt(); }
    
  2. ThreadPoolExecutor,然后使用shutdownNow():

    ThreadPoolExecutor executor = new ....;
    executor.execute(new Worker()); 
    
    // some lines else later
    executor.shutdownNow();  // shutdown() doesn't interrupt?
    

处理此类工作流的方法是什么?为什么?欢迎所有想法。

【问题讨论】:

  • cleanUp(); 应该在 finally 块中,除非您想在发生意外异常时保持数据库连接打开。

标签: java multithreading concurrency interrupt


【解决方案1】:

总的来说,我个人认为将isAlive 设置为false 是最干净的。 据我所知,interrupt() 是原生代码,这本身就是一个远离的原因。

不要忘记将boolean 设置为volatile

【讨论】:

  • 谢谢。其实我更喜欢使用 AtomicBoolean。更改代码以反映这一点。在某些情况下,volatile 可能会影响性能,尤其是对于频繁访问。
  • 一般来说 volatile 是一种更便宜的方法。原子变量只是有更多的灵活性......而且不用担心这么小的性能损失。它会浪费您的时间,并且总体上对整体应用程序的影响可以忽略不计。您需要担心的是 I/O 操作和 TCP 连接。
  • 非常正确,在这种情况下并不重要。
    记住volatilestatic 一起使用时会成为一个问题,并且有很多线程访问它。
【解决方案2】:

我认为这两种方法都是可以接受的。如果您有很多线程,我会使用线程池方法以便于管理。如果你只有一个(也许两个)线程,我会单独中断它们。

正如 MouseEvent 所说,不使用中断并使用 isAlive 变量会更干净(这在您的实现中似乎毫无意义)。但是,这意味着您需要关闭或关闭每个实例(仍然是一个好方法)

另外,我会将整个方法包含在 try-catch-finally 语句中,您可以在其中捕获中断并在 finally 子句中进行清理。

【讨论】:

  • 编辑并添加了更改 isAlive 的代码,我跳出了循环,因此它退出得更快。 try-catch-finally - 好主意。实际上,在 try 子句中放入更多代码/速度较慢的代码是否会降低性能?
  • 不...除非抛出异常,否则不会降低性能。此外,isAlive 检查就在中断检查之前。我假设两者同时将你踢出去。如果有任何性能提升,那将远远小于一毫秒。
  • 添加了一些关于我为什么使用 Thread.interrupted() 的 cmets,稍微更改了代码以反映我的意思。谢谢。
猜你喜欢
  • 1970-01-01
  • 2013-10-09
  • 2011-05-27
  • 1970-01-01
  • 2012-08-25
  • 2010-12-08
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
相关资源
最近更新 更多