Reputation: 123
I am learning Java Concurrency. So came across this example online for it. I have written the following code. The issue is, even though the tasks are done executing, it looks like there is something additional that is being executed. So how do I find out what is being executed?
package com.test.executors;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;
import java.util.logging.Logger;
class MyObject {
private Integer number;
private Integer result;
public Integer getNumber() {
return number;
}
public void setNumber(Integer number) {
this.number = number;
}
public Integer getResult() {
return result;
}
public void setResult(Integer result) {
this.result = result;
}
}
class FactorialCalculator implements Callable<MyObject> {
private Integer number;
public FactorialCalculator(Integer number) {
this.number = number;
}
@Override
public MyObject call() throws InterruptedException {
System.out.println(Thread.currentThread().getName() + " started...");
MyObject object = new MyObject();
object.setNumber(number);
int result = 1;
if (0 == number || 1 == number) {
result = 1;
} else {
for (int i = 2; i <= number; i++) {
result *= i;
TimeUnit.SECONDS.sleep(1);
}
}
object.setResult(result);
System.out.println(Thread.currentThread().getName() + " done...");
return object;
}
}
public class ExecutorMain1 {
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(3);
List<Future<MyObject>> results = new ArrayList<>();
Random random = new Random();
System.out.println("Starting Services...");
for (int i = 0; i < 5; i++) {
Integer number = random.nextInt(10);
Future<MyObject> result = service.submit(new FactorialCalculator(number));
results.add(result);
}
System.out.println("Done submitting tasks...");
System.out.println("Will display results shortly...");
for (Future<MyObject> future : results) {
try {
System.out.println("Number: " + future.get().getNumber() + "--> Result: " + future.get().getResult() + " Task Status: " + future.isDone());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
System.out.println("Exiting main...");
}
}
The output is -
Starting Services...
Done submitting tasks...
Will display results shortly...
pool-1-thread-2 started...
pool-1-thread-2 done...
pool-1-thread-2 started...
pool-1-thread-2 done...
pool-1-thread-2 started...
pool-1-thread-2 done...
pool-1-thread-1 started...
pool-1-thread-1 done...
Number: 6--> Result: 720 Task Status: true
Number: 5--> Result: 120 Task Status: true
pool-1-thread-3 started...
pool-1-thread-3 done...
Number: 4--> Result: 24 Task Status: true
Number: 0--> Result: 1 Task Status: true
Number: 1--> Result: 1 Task Status: true
Exiting main...
After Exiting main...
, the program doesn't exit yet. It is blocking on something. The 5 tasks that are submitted are done as well. So what is being executed? How do I find that out?
Upvotes: 0
Views: 52
Reputation: 11030
One minor comment on your "found code:" InterruptedException
is almost solely useful as a request for a thread to exit. Treating it as a normal exception is often a mistake. This line of code:
} catch (InterruptedException e) {
e.printStackTrace();
}
Is probably not useful, there's no reason to print a stack trace just because you've been requested to exit.
Also, when you catch an InterruptedException
and you DO NOT THROW IT, you must reset the interrupted flag for your thread.
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
This is because the other parts of the code must know that they are in an interrupted state and that they must exit as soon as possible.
C.f. Brian Goetz's Java Concurrency in Practice
Upvotes: 1
Reputation: 8758
JVM will not exit while there are non-daemon threads running.
And your ExecutorService
creates non-daemon worker threads. So to allow JVM to terminate you need to shutdown executor service. By calling either shutdown()
or shutdownNow()
since all your tasks already finished.
Upvotes: 4