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卸载信息:正在等待释放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()。由于某种原因,超过超时的futures仍然返回isDone()=false-没有被timout取消:(

感谢您的帮助。提前感谢。

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
}

最新更新