1

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

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());

我的控制台说:关机:真

我的可调用:

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 卸载信息:等待 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 取消:(

任何帮助表示赞赏。提前致谢。

4

1 回答 1

2

shutdownNow()杀死所有仍在运行的作业,这可能是错误消息的原因。您可能希望shutdown()它不会让任何新作业被提交,但让已排队的作业仍然执行。

此外,您需要通过调用等待期货完成future.get()(如果未来尚未完成,则可能会阻塞)以获取结果。

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

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

我已经重新检查了javadoc future.get(long timeout, TimeUnit unit),它并没有说如果发生超时,那么未来就会被取消。我还检查了 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
}
于 2013-08-20T14:06:50.570 回答