Будущий объект, имеющий ссылку на объект перед выполнением оператора return метода call () - PullRequest
0 голосов
/ 26 апреля 2018

Ниже приведена моя программа и вывод.

Еще до выполнения оператора return метода call () ( строка 1 ) для каждого цикла ( строка 2 ) выводится ссылка на переменную Future f, которая не равна нулю .

Мой вопрос здесь заключается в том, как это возможно, что будущая переменная указывает на некоторые объекты вместо нуля, прежде чем оператор return выполнится и назначит объект для f, как это работает внутри.

КОД: -

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**
}

}

ВЫХОД: -

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 

Ответы [ 2 ]

0 голосов
/ 26 апреля 2018

На самом деле именно здесь вы присваиваете значение f

f = es.submit(p);

После этой строки f больше не является нулевым. Это объект с типом будущее. Вы можете видеть это из системы - она ​​печатает java.util.concurrent.FutureTask@135fbaa4, который в основном является объектом типа FutureTask.

Когда ваш поток завершает свою работу, он не меняет значение f -> он все еще является объектом типа future, но он завершил свое выполнение (в основном isDone () становится true). После завершения вы можете получить фактический результат из:

f.get();

И вы можете проверить, закончил ли он с:

f.isDone()
0 голосов
/ 26 апреля 2018

Создание Future является синхронным и достигается в основном вызывающем потоке. Когда вы отправляете Callable на ThreadPoolExecutor, это работает так:

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;
}

Хотя выполнение future.get() не вернется, пока не будет выполнено задание или оно прервано или истекло время ожидания.

...