【发布时间】:2016-10-26 02:19:45
【问题描述】:
我有一个基于 JSP 的 (java) Web 应用程序。在这个应用程序中,我可以通过执行外部命令,根据 IP 向机器 (PC) 询问它们的状态和实际操作系统。
为了加速请求,我想使用线程同时询问更多机器,即 ExecutorService。
相应视图的 preRenderView 监听器设置为这个方法,我收集所有必须显示的数据。这里我初始化执行器,声明为私有静态类字段(private static ExecutorService executor):
public void selectData( ComponentSystemEvent event )
{
AmtRoomMachinesListController.executor = Executors.newFixedThreadPool(20);
AmtRoomMachinesListModel amtRoomMachinesListModel = (AmtRoomMachinesListModel)getModel();
List< ListRow > listRows = fetchListRows( amtRoomMachinesListModel );
...
}
在fetchListRow 中调用执行器并提交可调用对象。然后执行器被关闭并终止:
private List< ListRow > fetchListRows( AmtRoomMachinesListModel amtRoomMachinesListModel )
{
...
List< ListRow > listRows = Collections.synchronizedList( new ArrayList< ListRow >() );
for ( Machine machine : room.getRoomPCs() )
{
executor.submit( new AmtcWorker( listRows, machine, amtRoomMachinesListModel ) );
}
executor.shutdown();
try
{
executor.awaitTermination( 20, TimeUnit.SECONDS );
}
catch ( InterruptedException e )
{
throw new BootrobotException( ExceptionType.AMTC_ERROR, "command", "Waiting for thread termination", "error", e.getMessage() );
}
((ThreadPoolExecutor)executor).purge();
LOGGER.info( "Executor is shut down: " + executor.isShutdown() );
LOGGER.info( "Executor is terminated: " + executor.isTerminated() );
sortListRows( listRows );
return listRows;
}
我的问题是进程/线程的数量不断增加,一段时间后我得到 OutOfMemory 异常。每次调用selectData,进程数会根据提示的机器数增加。
我是线程新手,但我认为执行程序会在调用 executor.shutdown() 或 executor.awaitTermination 或 executor.purge() 时通过终止/杀死生成的线程来处理它们。
我错过了什么?
【问题讨论】:
-
为每个请求创建一个新的执行器是可疑的。您可能应该创建一个执行程序并将其用于所有请求。
-
你有没有试过在 Executor 完成后清空引用?除此之外,我第二个 @OldCurmudgeon 。您可能应该创建一个“全局”ExecutorService 并使用InvokeAll。
-
您的代码中有日志记录语句。日志显示什么?等等——显然,你的
executor是你的类中的一个static变量,你可以从实例方法中使用它。那是要求混乱。每次调用selectData时都会覆盖该变量,即使其他对象仍在使用它。因此,您无法控制哪个执行器将被关闭(或多久关闭一次)以及哪个永远不会关闭。 -
你不应该使用 AmtRoomMachinesListController.executor.shutdown(); ?或者你能给我们函数 fetchListRows 的完整代码
-
我同意@OldCurmudgeon,你应该创建一次执行器而不是关闭它,如果你想等待结果,你可以使用 CountDownLatch 例如
标签: java multithreading out-of-memory executorservice