Установите Платформу веб-инструментов, и вы сможете использовать ее поддержку для JSP. Наиболее важной частью для этого является Eclipse Java Web Developer Tools , но вам понадобится Eclipse Java EE Developer Tools , если вы хотите использовать Eclipse для запуска и отладки вашего веб-приложение на сервере.
Вы были бы более обеспеченным использованием get()
метод.
futureOne.get();
futureTwo.get();
, Оба из которых ожидают уведомления от потока, что это закончило обрабатывать, это сохраняет Вас busy-wait-with-timer, который Вы теперь используете, который не эффективен, ни изящен.
В качестве награды, у Вас есть API get(long timeout, TimeUnit unit)
, который позволяет Вам определять максимальное время для потока, чтобы спать и ожидать ответа, и иначе продолжает работать.
Посмотрите Java API для большего количества информации
Решение Yuval прекрасно. Как альтернатива можно также сделать это:
ExecutorService executor = Executors.newFixedThreadPool();
FutureTask<Object> futureOne = new FutureTask<Object>(myFirstProcess);
FutureTask<Object> futureTwo = new FutureTask<Object>(mySecondProcess);
executor.execute(futureOne);
executor.execute(futureTwo);
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
// interrupted
}
, Каково преимущество этого подхода? Нет большого различия действительно за исключением того, что этот способ, которым Вы останавливаете исполнителя, принимающего больше задачи (можно сделать это другой слишком). Я склонен предпочитать эту идиому той все же.
кроме того, если любой добирается () выдает исключение, можно закончить в части кода, который предполагает, что обе задачи сделаны, который мог бы быть плохим.
Можно хотеть использовать CyclicBarrier, если Вы интересуетесь запуском потоков одновременно или ожиданием их, чтобы закончиться и затем сделать некоторую последующую обработку. Посмотрите javadoc для получения дополнительной информации.
Использование FutureTask
выше допустимо, но определенно не идиоматично. Фактически вы обертываете дополнительную FutureTask
вокруг той, которую вы отправили в ExecutorService
. Ваша FutureTask
обрабатывается как Runnable
службой ExecutorService
. Внутри он заключает вашу FutureTask
-as- Runnable
в новую FutureTask
и возвращает ее вам как Future >
.
Вместо этого вы должны отправить экземпляры Callable
в службу CompletionService
. Вы вводите две Callable
через submit (Callable
, затем развернитесь и дважды вызовите CompletionService # take ()
(по одному разу для каждого отправленного Callable
). Эти вызовы будут блокироваться до тех пор, пока одна, а затем и другие отправленные задачи не будут выполнены.
Учитывая, что у вас уже есть Executor
в руке, создайте вокруг него новую ExecutorCompletionService
и отбросьте свои задачи там. Не крутите и не спите в ожидании; CompletionService # take ()
будет блокироваться до тех пор, пока одна из ваших задач не будет завершена (либо завершена, либо отменена), либо пока поток, ожидающий на take ()
, не будет прерван.
ExecutorCompletionService
вокруг нее и поместите туда свои задачи. Не крутите и не спите в ожидании; CompletionService # take ()
будет блокироваться до тех пор, пока одна из ваших задач не будет завершена (либо завершена, либо отменена), либо пока поток, ожидающий на take ()
, не будет прерван. создайте новую ExecutorCompletionService
вокруг нее и поместите туда свои задачи. Не крутите и не спите в ожидании; CompletionService # take ()
будет блокироваться до тех пор, пока одна из ваших задач не будет завершена (либо завершена, либо отменена), либо пока поток, ожидающий на take ()
, не будет прерван.