使用中断Java Runnable并运行清理的首选方法是什么?

时间:2015-03-09 21:21:48

标签: java multithreading concurrency interrupt

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

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. Runnables中关闭Threads,然后使用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?
    
  3. 处理此类工作流程的方法是什么?为什么?欢迎所有想法。

2 个答案:

答案 0 :(得分:0)

总而言之,我个人认为将isAlive设置为false是最干净的。 根据我的知识,interrupt()是本机代码,这是远离它的原因。

不要忘记将boolean设置为volatile

答案 1 :(得分:0)

我认为两者都是可接受的方法。如果你有很多线程,我会使用线程池方法来更容易管理。如果你只有一个(也许是两个)线程,我会单独打断它们。

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

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