IceMan
IceMan

Reputation: 123

What is the additional task that is being executed when using ExecutorService?

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

Answers (3)

markspace
markspace

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

Ivan
Ivan

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

xingbin
xingbin

Reputation: 28289

You need call shutdown explictly to terminate the threads in the pool. After this, the jvm can shutdown.

service.shutdown();
System.out.println("Exiting main...");

Upvotes: 1

Related Questions