Java threadPoolExecutor outOfMemoryException
我有一个带有run方法的类,该类的主方法中的计时器正在使用以下代码调用该类:Java threadPoolExecutor outOfMemoryException,java,multithreading,concurrency,Java,Multithreading,Concurrency,我有一个带有run方法的类,该类的主方法中的计时器正在使用以下代码调用该类: Timer timer = new Timer(); timer.scheduleAtFixedRate(new LegacySmsSender(), 0, 2*1000); 在run方法中,我声明了一个ThreadExecutorPool: ThreadPoolExecutor packetProcessorThreadPool = new ThreadPoolExecutor(4,
Timer timer = new Timer();
timer.scheduleAtFixedRate(new LegacySmsSender(), 0, 2*1000);
在run方法中,我声明了一个ThreadExecutorPool:
ThreadPoolExecutor packetProcessorThreadPool =
new ThreadPoolExecutor(4,
4,
Long.MAX_VALUE,
TimeUnit.DAYS,
new LinkedBlockingQueue<Runnable>(),
new MyThreadFactory("packetProcessorThreadPool")
);
在这些PacketProcessor类的run方法中,它们声明了一个ThreadPoolExecutor,并创建和提交了数量在1-5000之间的线程(通常创建6-7个线程),PacketProcessor中的ThreadPoolExecutor代码如下:
ThreadPoolExecutor commonThreadPool =
new ThreadPoolExecutor(
20,
20,
Long.MAX_VALUE,
TimeUnit.DAYS,
new LinkedBlockingQueue<Runnable>(),
new MyThreadFactory("commonThreadPool"));
threadpool执行器commonThreadPool=
新线程池执行器(
20,
20,
Long.MAX_值,
时间单位:天,
新建LinkedBlockingQueue(),
新MyThreadFactory(“commonThreadPool”);
最后,我运行了大约20分钟,我检查了VisualVM,我的内存使用和实时线程数一直在上升。有什么问题
注意:请随时向我询问更多信息或问题
以下是包含一些信息的屏幕截图:
编辑1:
我获取了270MB的堆转储。我发现了160mb的字符[]。我发现了大约1000-2000000个查询字符串。我使用StringBuilder构建查询字符串。为什么他们没有获得GCD 执行器应该在应用程序启动时声明一次并重新使用。否则,您也可以根据需要创建单个线程。如果在应用程序执行期间继续创建新的执行器,则它们的线程将保持运行,因此线程数将不断增加
因此,只需使用DI框架创建执行器,并将其注入到代码中即可。或者,如果它是一个小项目,将它们放在一个静态字段中。执行者应该在应用程序启动时声明一次并重新使用。否则,您也可以根据需要创建单个线程。如果在应用程序执行期间继续创建新的执行器,则它们的线程将保持运行,因此线程数将不断增加 因此,只需使用DI框架创建执行器,并将其注入到代码中即可。或者,如果是一个小项目,将它们放在一个静态字段中 在run方法中,我声明了一个ThreadExecutorPool 如果您在run方法中声明ThreadExecutorPool,该方法每2秒执行一次,您将在几分钟内获得许多线程 在run方法中,我声明了一个ThreadExecutorPool
如果在run方法中声明ThreadExecutorPool,该方法每2秒执行一次,那么在几分钟内就会得到许多线程。问题在于,您已经告诉了所有创建的
ExecutorService
来生成线程,然后让它们永远保持活动状态。这在代码中非常明显:
new ThreadPoolExecutor(
20,
20,
Long.MAX_VALUE,
TimeUnit.DAYS,
new LinkedBlockingQueue<Runnable>(),
new MyThreadFactory("commonThreadPool"));
新线程池执行器(
20,
20,
Long.MAX_值,
时间单位:天,
新建LinkedBlockingQueue(),
新MyThreadFactory(“commonThreadPool”);
第三个和第四个参数基本上是说“让空闲线程(实际上)无限期地保持活动状态”
您可以通过以下两种方式解决此问题:
ScheduledExecutorService
和更合理的任务分配逻辑来限制线程数量,并通过防止线程上下文切换来提高性能问题是,您已经告诉了所有创建的
ExecutorService
s来生成线程,然后让它们永远保持活动状态。这在代码中非常明显:
new ThreadPoolExecutor(
20,
20,
Long.MAX_VALUE,
TimeUnit.DAYS,
new LinkedBlockingQueue<Runnable>(),
new MyThreadFactory("commonThreadPool"));
新线程池执行器(
20,
20,
Long.MAX_值,
时间单位:天,
新建LinkedBlockingQueue(),
新MyThreadFactory(“commonThreadPool”);
第三个和第四个参数基本上是说“让空闲线程(实际上)无限期地保持活动状态”
您可以通过以下两种方式解决此问题:
ScheduledExecutorService
和更合理的任务分配逻辑来限制线程数量,并通过防止线程上下文切换来提高性能我尝试将它们用作静态,但它根本没有改变这个分析器上的图像。活动线程从未减少的原因是什么?我尝试将它们用作静态线程,但它根本没有改变这个分析器上的图像。活动线程从不减少的原因是什么?不。在run方法中,我等待线程完成,因此,在第一次运行
LegacySmsSender
完成之前,计时器不会再次启动。您的run方法中是否有定期执行的此代码?:ThreadPoolExecutor packetprocessorhreadpool=new ThreadPoolExecutor(…此代码位于计时器执行的操作的run方法中,将其输出到其他位置或执行packetprocessorreadpool.shutdown()操作);在某个地方。如果您将它放在其他地方,然后像@artbristol suggestedno那样创建一次会更好。在run方法中,我会等待线程完成,因此在第一次运行LegacySsender
完成之前,计时器不会再次启动。您的run方法中是否有定期执行的代码?:ThreadPoolExecutorpacketProcessorThreadPool=new ThreadPool Executor(…此代码位于计时器执行的对象的run方法中,该对象将其输出到其他位置或执行packetProcessorThreadPool.shutdown();某个地方。如果你把它放在其他地方,然后像@artbristol suggestedi那样创建一次,那会更好。我在1号上尝试了这个解决方案,在我创建后在TPEs上调用了shutdown