Это - некоторый пример кода от примера. То, что я должен знать, когда call()
обращен вызываемое? Что инициировало его?
public class CallableExample {
public static class WordLengthCallable
implements Callable {
private String word;
public WordLengthCallable(String word) {
this.word = word;
}
public Integer call() {
return Integer.valueOf(word.length());
}
}
public static void main(String args[]) throws Exception {
ExecutorService pool = Executors.newFixedThreadPool(3);
Set> set = new HashSet>();
for (String word: args) {
Callable callable = new WordLengthCallable(word);
Future future = pool.submit(callable); //**DOES THIS CALL call()?**
set.add(future);
}
int sum = 0;
for (Future future : set) {
sum += future.get();//**OR DOES THIS CALL call()?**
}
System.out.printf("The sum of lengths is %s%n", sum);
System.exit(sum);
}
}
После того, как вы отправили
вызываемый объект, исполнитель запланирует вызываемый объект для выполнения. В зависимости от исполнителя это может произойти напрямую или после того, как поток станет доступным.
Вызов get
, с другой стороны, ожидает только получения результата вычисления.
Чтобы быть точным: где-то между вызовом submit
и возвращением вызова get
вызывается вызываемый объект.
Вся идея использования Executor
заключается в том, что вам не нужно беспокоиться , когда именно вызывается метод .
Единственное, что обычно гарантируется, - это то, что метод будет выполнен, когда get ()
из Future
вернется.
Когда именно он будет вызван, зависит от того, какой Executor
вы используете. С фиксированным пулом потоков, который вы используете в примере, метод call ()
будет вызываться, как только появится свободный поток и никакая другая задача не будет перед данной задачей в очереди (чтобы пока имеется достаточно задач, в вашем примере в любой момент времени у вас будет 3 вызова метода call ()
).
Ответ на вопрос «когда будет вызываемый объект расписания» заключается в java.util.concurrent.ThreadPoolExecutor # выполнение реализации (по умолчанию)
{{ 1}}