Будущее - не удалось остановить поток

Я использую следующий код (схема):

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(mycallable);
        futures.add(future);
    }
for (Map.Entry<String, String> url : urls.entrySet())
    {
        try
            {
                status = (statusModel) futures.get(i).get(50, TimeUnit.MILLISECONDS);
                // do stuff with status
            }
        catch (InterruptedException | ExecutionException | TimeoutException e) 
            {
                System.out.println("Error<checkServers>: Timeout OR "+e.getMessage());
            }   
    }

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

Моя консоль говорит: Завершение работы: правда

myCallable:

public statusModel call() throws Exception 
{
    InputStream in = null;
    BufferedReader br = null;
    statusModel status = new statusModel();

    try 
    {
        URL url = new URL(urlStr);          
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        status.setStatusCode(conn.getResponseCode());
        status.setUrl(urlStr);

        if(status.getStatusCode()/100 == 2) // Status = OK
        { // Read JSON response  } 
            }
    catch (MalformedURLException e) 
    {
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } 
    catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    finally
    {
        if(in != null)
            in.close();
        if(br != null)
            br.close();
    }

    return status;
}

Иногда, когда я запускаю этот блок снова и снова, я получаю эту ошибку:

20 августа 2013 г. 9:35:44 org.apache.catalina.core.StandardWrapper unload INFO: Ожидание освобождения 1 экземпляра (ов) 20 августа 2013 г. 9:35:45 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads SEVERE: веб-приложение [/Server_Status] все еще обрабатывает запрос, который еще не завершен. Это очень вероятно, чтобы создать утечку памяти. Вы можете контролировать время, отведенное на завершение запросов, используя атрибут unloadDelay стандартной реализации Context. 20 августа 2013 г. 9:35:45 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads SEVERE: Похоже, что веб-приложение [/Server_Status] запустило поток с именем [pool-3-thread-6], но не смог остановить Это. Это очень вероятно, чтобы создать утечку памяти.

Я выключил 'executor' и проверил то же самое. Тем не менее я получаю эту ошибку. Я что-то здесь не так делаю?

Обновление: я использую Future впервые. Если мне нужно написать больше, чтобы объяснить лучше, пожалуйста, дайте мне знать.

Обновление: я попытался распечатать все future.isDone(). По какой-то причине фьючерсы, которые выходят за пределы тайм-аута, все еще возвращают isDone() = false - не отменяются тайм-аутом:(

Любая помощь приветствуется. Заранее спасибо.

1 ответ

Решение

shutdownNow() убивает все задания, которые все еще выполняются, что, вероятно, является причиной сообщения об ошибке. Вы, вероятно, хотите shutdown() что не позволит отправлять новые задания, но позволяет тем из них, которые были поставлены в очередь, по-прежнему выполняться.

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

for(Future<statusModel> future : futures){
  statusModel model = future.get();
  //do stuff with statusModel
}

РЕДАКТИРОВАТЬ: теперь, когда дополнительный код был опубликован, я добавил это к моему ответу:

Я перепроверил Javadoc для future.get(long timeout, TimeUnit unit)и это не говорит о том, что, если истекает время ожидания, то будущее отменяется. Я также проверил копию Java-параллелизма Брайана Гетца на практике (кстати, это отличная книга, которую нужно прочитать), и на странице 147 он рекомендует следующее:

try{
   future.get(timeout, unit);
}catch(TimeoutException e){
    //task will be cancelled below
}catch(ExecutionException e){
    //exception thrown in task; rethrow
    //... throw new MyWrappedException(e.getCause());
}finally{
    //Harmless if task already completed
    future.cancel(true); //interrupt if still running
}
Другие вопросы по тегам