我使用ThreadPoolExecutor
来运行线程。
ExecutorService executorService = Executors.newCachedThreadPool();
Future<?> future = executorService.submit(new MyRunnable());
基于某些条件,我需要终止长时间运行的线程并再次启动相同的线程实例(对于某些清理操作)。
由于我有一个未来的线程对象,我可以轻松检查它是否仍在运行。
future.isDone()
如果它正在运行,我可以使用
发送中断信号 future.cancel(true);
在MyRunnable
类中,处理中断信号。但是在循环开始时检查这个条件。
问题是future.isDone()
在发送中断信号后立即返回true。但我需要等到线程实例真正完成。
有没有办法检查线程是否真的在运行/完成?
答案 0 :(得分:1)
Apidoc还提到future.isDone()
如果future.cancel()
被调用则返回true,即它并不总是告诉你任务是否已经完成。
要检查任务是否已完成,您需要访问Runnable,然后您可以检查任务是否已完成或等待任务完成。
将下面的代码与它下面显示的输出进行比较,我想这会让您了解您的选择:
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Q21227864 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<?> future = executorService.submit(new MyRunnable());
sleep(100L);
future.cancel(true);
System.out.println("Future done: " + future.isDone());
sleep(100L);
future.cancel(true);
System.out.println("Future done: " + future.isDone());
sleep(500L);
System.out.println("Future done: " + future.isDone());
System.out.println("---");
MyRunnable mr = new MyRunnable();
future = executorService.submit(mr);
sleep(100L);
future.cancel(true);
System.out.println("Runnable done: " + mr.isDone());
sleep(100L);
System.out.println("Runnable done: " + mr.isDone());
mr.waitForCleanup();
System.out.println("Runnable done: " + mr.isDone());
executorService.shutdownNow();
}
public static void sleep(long timeMs) {
try { Thread.sleep(timeMs); } catch (Exception ignored) {}
}
static class MyRunnable implements Runnable {
final CountDownLatch completed = new CountDownLatch(1);
public void run() {
try {
System.out.println("Sleeping loop");
Thread.sleep(1000L);
System.out.println("Sleeping loop done");
} catch (Exception e) {
System.out.println("Stopped loop: " + e);
}
try {
System.out.println("Sleeping cleanup");
Thread.sleep(300L);
System.out.println("Sleeping cleanup done");
} catch (Exception e) {
System.out.println("Stopped cleanup: " + e);
}
completed.countDown();
}
public boolean isDone() {
return (completed.getCount() == 0);
}
public void waitForCleanup() {
try { completed.await(); } catch (Exception ignored) {}
}
}
}
输出:
Sleeping loop Future done: true Stopped loop: java.lang.InterruptedException: sleep interrupted Sleeping cleanup Future done: true Sleeping cleanup done Future done: true --- Sleeping loop Runnable done: false Stopped loop: java.lang.InterruptedException: sleep interrupted Sleeping cleanup Runnable done: false Sleeping cleanup done Runnable done: true
答案 1 :(得分:0)
我不认为future.isDone()会在发送中断信号后立即返回true。所有ThreadPoolExecutor任务都通过FutureTask.run()方法执行
public class FutureTask<V> implements RunnableFuture<V> {
...
public boolean isDone() {
return state != NEW;
}
public void run() {
...
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call(); <-- this invokes your code
ran = true;
} catch (Throwable ex) {
result = null; <-- if you threw InterruptedException
ran = false;
setException(ex); <-- state changes here
}
if (ran)
set(result); <-- if your code simply returns then state changes here
}
...