未来 - 线程未能停止

时间:2013-08-20 13:49:58

标签: java servlets future

我正在使用以下代码(大纲):

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;
}

有时当我反复运行此块时,我收到此错误:

  

2013年8月20日上午9:35:44 org.apache.catalina.core.StandardWrapper unload   信息:等待1个实例被解除分配   2013年8月20日上午9:35:45 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads   严重:Web应用程序[/ Server_Status]仍在处理尚未完成的请求。这很可能造成内存泄漏。您可以使用标准Context实现的unloadDelay属性来控制请求完成所允许的时间。   2013年8月20日上午9:35:45 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads   严重:Web应用程序[/ Server_Status]似乎已启动名为[pool-3-thread-6]的线程,但未能将其停止。这很可能会造成内存泄漏。

我关闭'执行者'也检查了相同。我仍然得到这个错误。我在这里做错了吗?

更新: 我是第一次使用Future。如果我需要发布更多信息以便更好地解释,请告诉我。

更新: 我尝试打印所有future.isDone()。由于某种原因超出超时的期货仍然返回isDone()= false - 没有被timout取消:(

感谢任何帮助。在此先感谢。

1 个答案:

答案 0 :(得分:2)

shutdownNow()会终止仍在运行的所有可能导致错误消息的作业。您可能希望shutdown()不会让任何新作业被提交,但让排队的作业仍然执行。

此外,您需要等待期货完成,方法是调用future.get()(如果未来尚未结束,可能会阻止)以获得结果。

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

编辑:现在已经发布了其他代码,我已将此附加到我的回答中:

我已经重新检查了future.get(long timeout, TimeUnit unit)的javadoc,并没有说如果超时发生,那么将来会被取消。我还检查了Brian Goetz的Java Concurrency in Practice(这是一本很棒的书;必读),并在第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
}