2015-02-04 4 views
0

Я знаю, что Callable позволяет вернуть значение или исключить исключение, тогда как Runnable этого не делает. Этот вопрос заключается не в разнице между двумя интерфейсами, а в последовательном возврате значений в следующем коде.Вызываемое последовательное выполнение

Пожалуйста, взгляните на следующий сегмент кода.

ExecutorService executorService = Executors.newCachedThreadPool(); 
    List<Future<String>> futureList = new ArrayList<Future<String>>(); 
    for (int i=0;i<10;i++) { 
     Runner runner = new Runner(i); 
     Future<String> future = executorService.submit(runner); 
     futureList.add(future); 
    } 
    executorService.shutdown(); 
    executorService.awaitTermination(1, TimeUnit.DAYS); 

    for (Future<String> integerFuture : futureList) { 
     System.out.println("Returned value is : " + integerFuture.get()); 
} 

Класс Runner для этого кода приведен ниже.

public class Runner implements Callable<String> { 

private int id; 

public Runner(Integer id) { 
    this.id = id; 
} 

@Override 
public String call() throws Exception { 

    Random randomWait = new Random(); 
    Thread.sleep(randomWait.nextInt(5)*1000); 

    Random random = new Random(); 
    int randomInt = random.nextInt(100); 
    return id + " - " + randomInt; 
} 
} 

Приведенный выше код всегда обеспечивает последовательный ответ, несмотря на то, что выполняемые им потоки могут спать в разные секунды.

Returned value is : 0 - 19 
Returned value is : 1 - 88 
Returned value is : 2 - 99 
........ 
Returned value is : 9 - 42 

Но для сравнения следующий сегмент кода обеспечивает более значимый отклик, так как потоки спят в разные периоды времени.

ExecutorService executorService = Executors.newCachedThreadPool(); 
for (int i=0;i<10;i++) { 
    Runner runner = new Runner(i); 
    executorService.submit(runner); 
} 
executorService.shutdown(); 
executorService.awaitTermination(1, TimeUnit.DAYS); 

Ниже представлен класс бегунов для сегмента. класса Runner общественности реализует Runnable {

private int id; 

public Runner(Integer id) { 
    this.id = id; 
} 

@Override 
public void run() { 

    Random randomWait = new Random(); 
    try { 
     Thread.sleep(randomWait.nextInt(5)*1000); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
    System.out.println("Runner : " + id + " Finished."); 

} 
} 

Как и следовало ожидать ответ этого потока является дискриминационным последовательным.

Runner : 5 Finished. 
Runner : 9 Finished. 
Runner : 1 Finished. 
Runner : 3 Finished. 
........ 

Так что мой вопрос в том, почему сегмент кода кулака с фьючерсами и отзывной ответ всегда последовательны? Мне кажется, что основной поток ждет до конца выполнения всех потоков и обеспечивает последовательный вывод. Но об этом не упоминается в джавадоке. Если бы ответ был чем-то наподобие второго, я мог бы это понять.

ответ

3

Сначала вы явно создать список фьючерсов с упорядоченными идентификаторами, то вы итерацию над ним в порядке:

for (Future<String> integerFuture : futureList) { 
    System.out.println("Returned value is : " + integerFuture.get()); 

Там нет никакого другого результата, но последовательные идентификаторы. Каждый раз, когда вы вызываете integerFuture.get(), звонок блокирует столько, сколько необходимо для будущего, чтобы обеспечить результат.

Во втором примере вы выводите на консоль от в пределахCallable, таким образом вы получаете выход в порядке завершения.

+0

Предположим, я хотел получить возвращаемые значения в зависимости от времени выполнения, как я мог это сделать? Некоторая идея была бы признательна. Спасибо за ваше время. –

+0

'long start = System.nanoTime(); ... обычный код ...; return System.nanoTime() - start; ' –

1

Итак, мой вопрос в том, почему сегмент кода кулака с фьючерсами и вызываемым ответом всегда последователен?

Потому что вы специально просят в результате Futures в том порядке, в котором они были представлены:

for (Future<String> integerFuture : futureList) { 
     System.out.println("Returned value is : " + integerFuture.get()); 

Здесь Future.get() будет блокировать, пока вызов не будет завершен - и список строится путем подачи вызовов; futureList.get(0) всегда будет будущим, связанным с первым вызываемым, независимо от того, является ли он первым до полным.

+0

Спасибо за ответ. Я очень ценю это. –

Смежные вопросы