ankshah
ankshah

Reputation: 435

When is runnable object garbage collected in ExecutorService?

I have a runnable object A which exchanges heart beat signals with a server on instantiation. I submit n such objects to a executor service with fixed thread pool size of n. When the run method encounters exception it would return. For a given case, all my threads encounter exception and return, but the object created remains alive and keeps on exchanging the heart beat signals. How do I mark such objects up for garbage collection so that they would stop the heart beat signals exchange?

class A implements Runnable {
    public void run(){
          try{
           \\throws error
          } catch(Exception e){
            \\returns
          }
       }

    public static void main(){
          ExecutorService executor = Executors.newFixedThreadPool(n)
          for(i = 1 to n){
               A a = new A()
               executor.submit(a)
          }
       }
}

Should I put a awaitTermination call at the end of my main and do a return?

Edit:
Putting the question other way, one way to terminate the executorservice after all the threads return would be to call shutdown() after the for loop and call awaitTermination with Integer.MAX long seconds which is roughly 70 years ( which is a time constraint I am reluctant to impose). Is there any other alternative?

Upvotes: 5

Views: 1934

Answers (3)

Maurice Perry
Maurice Perry

Reputation: 9648

The tasks themselves are eligible for garbage collecting as soon as their execution is complete. If and when they are actually collected depends on the garbage collector.

Example code:

public class Main implements Runnable {
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("finalize");
    }

    @Override
    public void run() {
        try {
            throw new Exception("Error");
        } catch (Exception e) {
            //returns
        }
    }

    public static void main(String args[]) {
        int n = 8;
        ExecutorService executor = Executors.newFixedThreadPool(n);
        for (int i = 0 ; i < n; ++i) {
            Main a = new Main();
            executor.submit(a);
        }
        System.gc();
        System.out.println("end");
    }
}

Upvotes: 0

Krzysztof Cichocki
Krzysztof Cichocki

Reputation: 6412

calling shutdown() on pool means the pool will no longer accept any new task for execution, but the current ones will run without interruption.

calling awaitTermination(timeout) holds the calling thread till the pool is finished, but if timeout is reached, then current thread throws execption, but it will not affect the tasks in pool.

If your runnable throws uncought exception when is run by thread pool, then this runnable is no longer in run state - thread pool doesn't hold any reference to such object usually.

If you use FixedThreadPool, then this pool will create as many threads as you wish, and will not stop any of them until you call shutdown() on this pool.

If you don't have reference to the runnable object that throwed the exception it behaves as regular unreferenced Object to be Garbage Collected.

if you call shutdown() and then awaitTermination() on thread pool, and your program doesn't stop anyway, that means not all instances of your runnable have thrown an exception, and some are still running thus blocking the pool from complete shutdown.

In java you can't kill or stop running thread just like that (you can only kill entire JVM using eg. System.exit(0), but not just choosen thread), if you need such functionality you need to program the body of the runnable in a way that lets you communicate somehow with it, ie. using some "volatile boolean" variable, and that it will respond to change in the value of this variable - it means that you need to add "if checks" for the value of this variable in the body of the run() method that will return when it should.

Upvotes: 0

nail fei
nail fei

Reputation: 2329

one way to terminate the executorservice after all the threads return would be to call shutdown() after the for loop and call awaitTermination with Integer.MAX long seconds which is roughly 70 years

as the doc says the awaitTermination method will block util:

  1. all tasks have completed execution after a shutdown request
  2. or the timeout occurs,
  3. or the current thread is interrupted, whichever happens first


So it will game over as soon as one of the three event turn up, rather than have to wait 70 years.

Upvotes: 1

Related Questions