springcloudlearner
springcloudlearner

Reputation: 457

Future Object having Object reference before return statement of call() method executes

Following is my program and output.

Even before the return statement of call() method is executed (line 1) the for each loop (line 2) prints the reference of Future variable f which is not null.

My question here is that how is that possible that future variable points to some objects instead of null before the return statement gets executed and assigns a object to f, how is this working internally.

CODE :-

import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ObjectPool2
{
    public static void main(String[] args) 
    {
        Pool[] pObject = {new Pool(),new Pool(),new Pool(),new Pool(),new Pool(),new Pool(),new Pool(),new Pool()};

    ExecutorService es = Executors.newFixedThreadPool(8);

    Future f = null;

    for(Pool p : pObject)                         **// line 2**
    {
        f = es.submit(p);
        System.out.println(f.toString());
        System.out.println(f);
        System.out.println(f);
        System.out.println(f);
        System.out.println("---------------");
        }

        System.out.println(f);
    }
}

class Pool implements Callable
{
    public static ConcurrentLinkedQueue unlocked_queue2 = new ConcurrentLinkedQueue();
    public static ConcurrentLinkedQueue locked_queue2 = new ConcurrentLinkedQueue();

static
{
    int i = 1;
    int i2 = 2;
    int i3 = 3;
    int i4 = 4;
    unlocked_queue2.add(i);
    unlocked_queue2.add(i2);
    unlocked_queue2.add(i3);
    unlocked_queue2.add(i4);
}

public Object get() throws InterruptedException
{
    synchronized(getClass())
    {
    while(unlocked_queue2.isEmpty())
    {
        System.out.println(Thread.currentThread().getName() + " waiting ");
        this.getClass().wait();
    }
    int op = (int)unlocked_queue2.poll();
    locked_queue2.add(op);
    System.out.println(Thread.currentThread().getName() + " got lock of : "+ op +" now going to sleep");
    Thread.currentThread().sleep(5000);
    return op;
    }
}

public void leave()
{
    synchronized(getClass())
    {
    int ol = (int)locked_queue2.poll();
    unlocked_queue2.add(ol);
    System.out.println(Thread.currentThread().getName() + " leaving lock of : "+ ol);
    this.getClass().notifyAll();
    }
}

@Override
public Object call() throws Exception
{
    Object lock = get();
    return lock;                                 **//line 1**
}

}

OUTPUT :-

java.util.concurrent.FutureTask@55f96302
java.util.concurrent.FutureTask@55f96302
java.util.concurrent.FutureTask@55f96302
java.util.concurrent.FutureTask@55f96302
---------------
pool-1-thread-1 got lock of : 1 now going to sleep
java.util.concurrent.FutureTask@42a57993
java.util.concurrent.FutureTask@42a57993
java.util.concurrent.FutureTask@42a57993
java.util.concurrent.FutureTask@42a57993
---------------
java.util.concurrent.FutureTask@6bc7c054
java.util.concurrent.FutureTask@6bc7c054
java.util.concurrent.FutureTask@6bc7c054
java.util.concurrent.FutureTask@6bc7c054
---------------
java.util.concurrent.FutureTask@4aa298b7
java.util.concurrent.FutureTask@4aa298b7
java.util.concurrent.FutureTask@4aa298b7
java.util.concurrent.FutureTask@4aa298b7
---------------
java.util.concurrent.FutureTask@28d93b30
java.util.concurrent.FutureTask@28d93b30
java.util.concurrent.FutureTask@28d93b30
java.util.concurrent.FutureTask@28d93b30
---------------
java.util.concurrent.FutureTask@4554617c
java.util.concurrent.FutureTask@4554617c
java.util.concurrent.FutureTask@4554617c
java.util.concurrent.FutureTask@4554617c
---------------
java.util.concurrent.FutureTask@1540e19d
java.util.concurrent.FutureTask@1540e19d
java.util.concurrent.FutureTask@1540e19d
java.util.concurrent.FutureTask@1540e19d
---------------
java.util.concurrent.FutureTask@14ae5a5
java.util.concurrent.FutureTask@14ae5a5
java.util.concurrent.FutureTask@14ae5a5
java.util.concurrent.FutureTask@14ae5a5
---------------
java.util.concurrent.FutureTask@14ae5a5
pool-1-thread-8 got lock of : 2 now going to sleep
pool-1-thread-7 got lock of : 3 now going to sleep
pool-1-thread-6 got lock of : 4 now going to sleep
pool-1-thread-5 waiting 
pool-1-thread-4 waiting 
pool-1-thread-3 waiting 
pool-1-thread-2 waiting 

Upvotes: 1

Views: 563

Answers (2)

xingbin
xingbin

Reputation: 28289

The creation of Future is synchronous and is achived in the main calling thread. When you submit a Callable to an ThreadPoolExecutor, it works like this:

public Future submit(Callable callable) {
    Future future = new FutureTask(callable);
    if (currentThread < coreThread) {
        createNewThreadWhichWillExecuteTheFutureAutomically(); // this will not get blocked, the thread will execute the future itself
    } else if (queueIsNotFull) {
        putTheFutureInQueue(future);
    } else if (currentThread < maxThread) {
        createNewThreadWhichWillExecuteTheFutureAutomically(); // this will not get blocked, the thread will execute the future itself
    } else {
       throw RejectedExecutionException();
    }
    return future;
}

While the execution of future.get() will not return untill the task has been executed or it is interrupt or timeout.

Upvotes: 1

Veselin Davidov
Veselin Davidov

Reputation: 7081

Actually this is where you assign a value to f

f = es.submit(p);

After that line f is no longer a null. It is an object with type future. You can see that from the system out - it prints java.util.concurrent.FutureTask@135fbaa4 which is basically an object of FutureTask type.

When your thread finishes it doesn't change the value of f -> it is still an object of type future but it has finished it execution (basically isDone() becomes true). Once it has finished you can get the actual result from:

f.get();

And you can check if it is already finished with:

f.isDone()

Upvotes: 0

Related Questions