I've got simple test code:
public static void main(String[] args) {
CompletionService<Integer> cs = new ExecutorCompletionService<>(Executors.newCachedThreadPool());
cs.submit(new Callable<Integer>() {
public Integer call(){
try{
Thread.sleep(3000); // Just sleep and print
System.out.println("Sleeping thread: " + Thread.currentThread().getId());
}catch(InterruptedException e){
e.printStackTrace();
}
return 10;
}
});
try{
Future<Integer> fi = cs.take();
System.out.println(fi.get());
}catch(Exception e){
e.printStackTrace();
}
}
I run it, sleep 3 seconds, and prints
Sleeping thread: 14
10
But then it hangs there, the program doesn't end.
What's happening, how to make it finish?
As mentioned in the comments by tgdavies, your program will exit after +/- 60 seconds, because that is the default timeout for a thread without tasks in an ExecutorService
created by Executors.newCachedThreadPool()
.
If you don't want to wait for 60 seconds, you should shutdown the executor service after you're done submitting tasks.
For example:
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
try {
CompletionService<Integer> cs = new ExecutorCompletionService<>(executorService);
cs.submit(new Callable<Integer>() {
public Integer call() {
try {
Thread.sleep(3000); // Just sleep and print
System.out.println("Sleeping thread: " + Thread.currentThread().getId());
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
}
});
try {
Future<Integer> fi = cs.take();
System.out.println(fi.get());
} catch (Exception e) {
e.printStackTrace();
}
} finally {
executorService.shutdown();
}
}
Alternatively, configure the executor service to create daemon threads using a custom ThreadFactory
. Only do this if it is not a problem that an executor service that is doing actual work gets "killed" when there are no more normal (non-daemon) threads.