ExecutorService和OutOfMemoryError:使用Executor时无法创建新的本机线程

时间:2016-10-24 12:57:40

标签: java multithreading out-of-memory executorservice

我有一个基于JSP的(java)Web应用程序。在这个应用程序中,我可以通过执行外部命令,向机器(PC)询问基于IP的状态和实际操作系统。

为了加快请求,我想要使用线程同时要求更多的机器,即ExecutorService。

相应View的preRenderView侦听器设置为此方法,我收集所有必须显示的数据。这里我初始化执行程序,它被声明为私有静态类字段(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; } 中调用执行程序并提交可调用程序。然后关闭并终止执行程序:

selectData

我的问题是进程/线程的数量不断增加,一段时间后我得到了OutOfMemory异常。每次调用res = opener.open(login_url, data) res.close() 时,进程数都会增加提示机器的数量。

我是新手与线程,但我认为执行者会在调用executor.shutdown()或executor.awaitTermination或executor.purge()时终止/终止它们来处理生成的线程。 / p>

我错过了什么?

2 个答案:

答案 0 :(得分:1)

使用一个ThreadPool。另外,你确认awaitTermination函数返回true吗?很可能awaitTermination在20秒内没有完成并返回false。新的线程池不断创建,而没有旧的线程池获得GCed并最终耗尽内存。

答案 1 :(得分:1)

我的建议是只创建一个线程池。线程池用于管理线程。如果你每次调用一个方法创建一个线程池,那么基本上它就像你每次调用一个方法时创建线程一样糟糕,但是如果你仍然坚持要创建多个线程池那么为什么不要你呢?试试这个

private List< ListRow > fetchListRows( AmtRoomMachinesListModel amtRoomMachinesListModel )
{
   ExecutorService executor = Executors.newFixedThreadPool(20);
...
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;
}

刚刚本地化了执行者