如何强制停止无限循环线程

时间:2019-05-14 07:44:26

标签: java multithreading

下面是一个代码段

ExecutorService executor = Executors.newSingleThreadExecutor();

executor.submit(() -> {
    while (true) System.out.println("1");
});
executor.shutdown();
executor.shutdownNow();

有什么方法可以从外部关闭执行器? (建议不能更改任务本身) 喜欢在Linux中杀死-9

4 个答案:

答案 0 :(得分:0)

有一些方法

  1. 在循环条件中添加其他条件,例如boolean shouldContinue,因此将其设置为false会在某些时候退出循环
  2. 如果您可以编写自己的功能(您拥有应用程序),则可以编写代码以列出所有线程,并强制给定线程停止使用Thread#stop(不安全)或Thread#interrupt(更安全)。 / li>
  3. 如果您不拥有该应用程序(例如您正在运行某些应用程序),则可以使用自定义javaagent来运行该应用程序,这将允许您执行第2点中的相同操作。

2和3都与探针(例如Sockets)集成,可以让您从外部运行已在运行的进程。从CLI

答案 1 :(得分:0)

为什么不使用ScheduledExecutorService而不是常规的ExecutorService?

您可以捕获Future(即正在执行(或将要执行)的任务),并根据需要从“外部”取消它。

public class Example {
    private ScheduledFuture mThread;
    private final ScheduledExecutorService mExecutor = Executors.newScheduledThreadPool(1);

    public void executeForever() {
        mThread = mExecutor.schedule(() -> { while (true) System.out.println("1"); }, 0, TimeUnit.NANOSECONDS);
    }

    public void cancelThread() {
        mThread.cancel(true);
    }
}

您的ScheduledFuture还将继承Future接口的所有方法,如cancel,get,isCancelled和isDone。

有关ScheduledFuture的更多信息:https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledFuture.html

有关ScheduledExecutorService的更多信息:https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledExecutorService.html

通过这种方式,您无需更改任务,只需执行任务即可。

答案 2 :(得分:0)

请阅读shutdownNow()方法的javadoc。它说得很清楚:

  

除了尽最大努力停止处理外,没有任何保证   积极执行任务。例如,典型的实现将   通过Thread.interrupt()取消,因此任何无法响应的任务   中断可能永远不会终止

因此,您需要做的是更改代码中提交的任务以响应Thread.interrupt()方法。即您需要将行
while (true)
更改为
while (true && !Thread.currentTrhead().isInterrupted())
有关更多详细信息,请在特定方法{{1 }},interrupt()interrupted()

答案 3 :(得分:0)

如果公开线程,执行程序将在其上运行您,那么您可以中断它。对我来说,这仅打印1 4次,表明中断成功。

请记住,这取决于Thread.sleepSystem.out.println可中断的事实。如果您不检查Thread.isInterrupted(就像他们俩一样),您仍然可能无法中断线程。

ExecutorService executor = Executors.newSingleThreadExecutor();

private void test() throws InterruptedException {
    AtomicReference<Thread> thread = new AtomicReference<>();
    Future<Object> task = executor.submit(() -> {
        // Keep track of the thread.
        thread.set(Thread.currentThread());
        try {
            while (true) {
                Thread.sleep(1000);
                System.out.println("1");
            }
        } finally {
            System.out.println("Interrupted: " + Thread.currentThread().isInterrupted());
        }
    });
    Thread.sleep(5000);
    // Interrupt the thread.
    thread.get().interrupt();
    Thread.sleep(5000);
    System.out.println("Press <Enter> to shutdown");
    new Scanner(System.in).nextLine();
    executor.shutdown();
    System.out.println("Press <Enter> to shutdown NOW");
    new Scanner(System.in).nextLine();
    executor.shutdownNow();
}