我正在使用以下代码(大纲):
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
}