2013-08-19 3 views
3

В моем сервлете я нажимаю несколько URL-адресов, чтобы проверить их статус и вернуть ответ пользователю.Правильная реализация многопоточности Java Future

Захват запросов многопроцессор занимает много времени: нужны потоки и тайм-ауты. Но мне нужны мои потоки, чтобы получить ответ: используя будущее по этой причине.

Мой код очертание:

ExecutorService executor = Executors.newFixedThreadPool(10); 
Future<statusModel> future; 

for (Map.Entry<String, String> url : urls.entrySet()) 
{ 
    try 
    { 
     future = executor.submit(new CallableRequestStatus(url.getValue())); 
     status = (statusModel) future.get(5, TimeUnit.SECONDS); 
     results.add(status); 
    } 
    catch (InterruptedException | ExecutionException | TimeoutException e) 
    { 
     System.out.println("Error<checkServers>: Timeout OR "+e.getMessage()); 
    } 
} 
executor.shutdownNow(); 

Все результаты моего отзывной класса приходит в объект состояния, который я позже добавить к ArrayList. Моя проблема в том, что мой подход блокирует меня от запуска всех 10 потоков одновременно. Мне нужно подождать 5 секунд для получения моего объекта статуса, а затем перейти к следующему URL.

Я думаю, что мой подход неисправен. Я пробовал смотреть в Интернете, но я не мог найти ни одного примера с пользовательскими объектами и вовлеченным Arraylist.

Может кто-нибудь помочь мне исправить свою вину. Заранее спасибо

Наконец Обновленный мой код (спасибо Sotirios Delimanolis и Kevin):

ExecutorService executor = Executors.newFixedThreadPool(20); 
List<Future<statusModel>> futures = new ArrayList<Future<statusModel>>(); 

for (Map.Entry<String, String> url : urls.entrySet()) 
{ 
    Future<statusModel> future = executor.submit(new CallableRequestStatus(url.getValue())); 
    futures.add(future); 
} 

ArrayList<statusModel> results = new ArrayList<statusModel>(); 
statusModel status; 

int i=0; 

for (Map.Entry<String, String> url : urls.entrySet()) 
{   
    try 
     { 
      status = (statusModel) futures.get(i).get(500, TimeUnit.MILLISECONDS); 
      // do some stuff with status and 

      if(status.getStatusCode()/100 == 2) 
       results.add(status); 
     } 
    catch (InterruptedException | ExecutionException | TimeoutException e) 
     { 
      System.out.println("Error<checkServers>: Timeout OR "+e.getMessage()); 
     } 
i++; 
} 

executor.shutdownNow(); 
System.out.println("Shutdown: "+executor.isShutdown()); 

Надежда его полезным для кого-то :)

+6

Добавить все фьючерсы в набор или список. После того, как вы отправили все свои вызовы, пройдите через элементы 'Future' и вызовите' get' без значения таймаута. Ваш основной поток будет блокироваться, но другие задачи будут продолжать выполняться. Вы будете в основном ждать длительности самого долгого срока. –

+0

Спасибо Sotirios за быстрый ответ. Я пробовал то, что вы предлагали, но я все еще зацикливаюсь, когда я зацикливаюсь на futureList для серверов, которые занимают слишком много времени. –

+0

Если вам нужно дождаться ответа всех серверов и получить все их результаты, это единственный синхронный способ сделать это. –

ответ

2

Вы должны представить все авансовые, а затем ждать отдельно. Как показано ниже, удаление исключений для ясности:

ExecutorService executor = Executors.newFixedThreadPool(10); 
List<Future<statusModel>> futures = new ArrayList<>(); 

for (Map.Entry<String, String> url : urls.entrySet()) 
{ 
    futures.add(executor.submit(new CallableRequestStatus(url.getValue()))); 
} 
for (Future<statusModel> f : futures) { 
    results.add((statusModel) f.get(5, TimeUnit.SECONDS)); 
} 
+0

Привет, Кевин, спасибо или быстрый ответ. Я просто попробовал то, что вы и @ Сотириос предложили. Это определенно выглядит как правильный способ реализации, однако, когда я ударяю свои запросы, я все еще вижу, что запросы обрабатываются один за другим. Таким образом, если сервер один застопорился .. только после того, как его время ожидания сервера 2 проверено и сервер 3. В этом подходе, если из 20 5 пунктов ожидания в течение 5 секунд мое время отклика составляет 25 + сек. –

+0

Если вы установите тайм-аут в вызываемом, но вам не нужно блокировать получение, и вы можете просто проверить future.isDone() – lscoughlin

+0

lscoughlin, если я тайм-аут в моем вызываемом мне все равно придется использовать get to collect мои результаты были. Итак, когда я зациклился на своем будущемList, я все равно застрял бы в ответах на временные ответы? –

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