1

我有一个应用程序,它在一个单独的线程中的 while 循环中重复运行某些东西,直到用户触发关闭信号。我可以通过在工作线程中设置一个(易失的)布尔字段来将信号从主线程发送到工作线程,但是有没有其他方法可以关闭/中断线程,例如通过'java.util中的任何实用程序。同时'?

我曾尝试调用 ExecutorService 的 shutdown() 或 shutdownNow() 方法,但它们无法停止工作线程。同样调用shutdown() 并按照此处!Thread.currentThread().isInterrupted()推荐的在while 条件下使用是无法打破循环。我能找到的唯一另一种方法是使用 CountDownLatch,但在这里我必须在条件 for while 循环中使用,但这种方法的 javadoc 文档说CountDownLatch.getCount() != 0

此方法通常用于调试和测试目的。

这使得它成为 IMO 的一个值得商榷的方法。下面是我的示例代码

class Worker implements Runnable {
    //private volatile boolean shutdown = false; --> alternative to countdownlatch 
    @Override
    public void run() {

        while (countDownLatch.getCount() != 0) {
            //do some work    
        }
    }
}

public class App {
    public static void main(String[] args) {

    System.out.println("Press enter to stop");

    CountDownLatch countDownLatch = new CountDownLatch(1);

    ExecutorService es = Executors.newFixedThreadPool(1);
    es.execute(new Worker(countDownLatch));

    Scanner scanner = new Scanner(System.in);
    scanner.nextLine();

    System.out.println("Shut down signal received");

    countDownLatch.countDown();  //an alternative would be to set a boolean variable in worker

    es.shutdownNow();

}
}

还有其他干净的方法吗?

4

3 回答 3

2

还有其他干净的方法吗? 不。 坚持使用 ( volatile ) 布尔值。

我确信 Thread.stop() 会起作用,但没有机会正确清理。使用 interrupted()/isInterrupted() 会起作用,但它比布尔值要复杂一些。另外,有时您不想仅仅因为循环被中断而退出循环。我在几个地方有代码,我从 InterruptedException(或类似的东西)中恢复,然后检查我的布尔值(或其他),并根据它的值,继续与否。

布尔值可以很好地与其他人一起使用。我已经提到了中断。有一天,您可能有 20 个不同的理由在 10 个(或更多)位置中的任何一个处停止循环。该布尔值将适合;您可以轻松编写代码,以便您的线程在布尔值为真时始终停止,或者在其为假时永远停止,或者您需要完成的任何其他操作。

于 2013-12-09T20:02:05.683 回答
1

您必须检查循环中的 Thread.interrupted(),以便使用 System.exit() 以外的任何内容将其关闭。然后你可以使用thread.interrupt(),这是ExecutorService.shutdown() 无论如何都要使用的。如果它不起作用,请向我们展示您如何检查 isInterrupted() 的代码,以便我们修复它。Thread.stop() 存在,但有充分理由不推荐使用,不应使用。

于 2013-12-09T00:47:43.110 回答
0

您可以从 [Executors][http://docs.oracle.com/ 获取 [ExecutorService][http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html] javase/7/docs/api/java/util/concurrent/Executors.html]

通过在主线程中引用 ExecutorsService,您可以在接收到信号时关闭 ThreadPool。

于 2013-12-09T07:05:36.920 回答