此代码挂起。我理解我将Future.get()称为未执行的未来,但我希望在future.get()方法上看到CancellationExcetpion或InterruptedException或其他一些异常。我错了吗?
public class ExecutorTest {
static ExecutorService executorService = Executors.newFixedThreadPool(1);
public static void main(String[] args) throws Exception {
List<Future> futures = new ArrayList<Future>();
for (int i = 0; i < 10; i++) {
Future<Object> future = executorService.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
System.out.println("Start task");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Finish task");
return "anything";
}
});
futures.add(future);
}
new Thread() {
@Override
public void run() {
try {
Thread.sleep(10000);
System.out.println("Shutdown Now");
executorService.shutdownNow();
} catch (InterruptedException e) {
System.out.println("Interrupted Exception during shutdown");
}
}
}.start();
for(Future f : futures) {
System.out.println("-------------------------");
System.out.println("before sleep");
Thread.sleep(3000);
System.out.println("after sleep...");
try {
f.get();
} catch (Exception ex) {
System.out.println("exception during future.get");
}
System.out.println("after get!");
}
}
}
这是我的输出
Start task
-------------------------
before sleep
after sleep...
Finish task
after get!
-------------------------
Start task
before sleep
after sleep...
Finish task
Start task
after get!
-------------------------
before sleep
after sleep...
Finish task
Start task
after get!
-------------------------
before sleep
Shutdown Now
Finish task
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at ru.pp.ExecutorTest$1.call(ExecutorTest.java:28)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
after sleep...
after get!
-------------------------
before sleep
after sleep...
Java 8,Intellij
如果我更换
System.out.println("Start task");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
用这个
System.out.println("Start task");
Thread.sleep(3000);
然后它不会挂起
我很沮丧......
答案 0 :(得分:3)
当您调用shutdownNow
时,ExecutorService
会删除所有已安排但尚未运行的任务,并将其作为List<Runnable>
返回给您。这些任务具有相应的Future
,您已经引用了它。由于这些任务永远不会运行,因此它们永远不会产生结果,即。永远不会完成因此,这些任务的Future#get()
将永远不会返回。
如果您愿意,可以使用
返回运行这些任务executorService.shutdownNow().forEach(r -> r.run());
您将看到所有Future#get()
次来电回复。
如果您知道任务已完成/取消,您应该只调用Future#get()
。或者,暂停一下。
答案 1 :(得分:0)
当Thread_1调用 FutureTask#get 时,将调用 Thread_1 #wait 。现在继续Thread_1应该由某人通知。仅当FutureTask终止时(在 FutureTask#set , FutureTask #setException 或 FutureTask#cancelning )上才会调用通知。但就我而言,由于shutdownNow(FutureTask处于NEW状态),FutureTask从未启动过。因此它从未被终止,并且从未调用过 Thread_1#notify 。 为了解决这个问题,我没有从 #shutdownNow 开始期货,也没有为他们调用 FutureTask#get 。
PS:老实说FutureTask使用sun.misc.Unsafe#park #unpark方法而不是wait and notify。