我正在无限制的流中读取 SQS 中的文件。当我读取每个文件时,我想将其提交到第二个队列进行处理。我可以同时处理几个文件,所以我将它们放入线程中,并希望在所有线程都在使用时阻止从队列中进一步读取。
为此,我使用了这个:
ExecutorService executorService =
new ThreadPoolExecutor(
maxThreads, // core thread pool size
maxThreads, // maximum thread pool size
1, // time to wait before resizing pool
TimeUnit.MINUTES,
new ArrayBlockingQueue<Runnable>(maxThreads, true),
new ThreadPoolExecutor.CallerRunsPolicy());
maxThreads = 2
。
文件以十个为单位进行读取并按原样处理:
for (Message msg : resp.getMessages()) {
Gson g = new Gson();
MessageBody messageBody = g.fromJson(msg.getBody(), MessageBody.class);
MessageRecords messageRecords = g.fromJson(messageBody.getMessage(), MessageRecords.class);
List<MessageRecords.Record> records = messageRecords.getRecords();
executorService.submit(new Runnable() {
@Override
public void run() {
... do some work based on file type
}
});
观察线程数我看到它一直稳步攀升,直到系统内存不足,用无法创建本机线程异常关闭作业。在此之后,VM(AWS)不会接受SSH登录,直到它被停止/重新启动。
似乎必须有一个给定线程被释放/清理的步骤,但我没有看到它应该发生在哪里。
我做错了什么?
run()
完成并退出run()
方法获取文件,查看类型并根据类型调用fn()。函数解析文件并返回。然后run()
完成了。答案 0 :(得分:0)
问题在于我使用ThreadPoolExecutor
。特别是它在应用程序进程中出现(s / ed)的位置。我通过一个SQS消息块为每个循环创建一个新的线程池,然后不关闭它。将此创建移到循环中并重复使用相同的块可以解决问题。
所以 - 一个大毛茸茸的UFU。