This code hangs. I understand that I call future.get() for the future that wasn't executed but I expect to see CancellationExcetpion or InterruptedException or some other exception on future.get() method. Am I wrong?
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!");
}
}
}
This is my output
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
If I replace
System.out.println("Start task");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
with this
System.out.println("Start task");
Thread.sleep(3000);
then it doesn't hang
I'm frustrated...
When Thread_1 calls FutureTask#get then Thread_1#wait is called. Now to continue Thread_1 it should be notified by somebody. Notification is called ONLY when FutureTask is terminated (on FutureTask#set, FutureTask#setException or FutureTask#cancel). But in my case the FutureTask was never started because of shutdownNow (FutureTask was in state NEW). So it was never terminated and Thread_1#notify was never called. To fix it I got all not started futures from #shutdownNow and didn't call FutureTask#get for them.
PS: Honestly FutureTask uses sun.misc.Unsafe#park #unpark methods instead of wait and notify.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments