Java - 重用线程池

Java - Reusing Thread Pool

对于我的 Java 项目,我想并行执行两个任务并合并它们的结果。问题是我必须在每次执行时调用多次(可能 1000 次或更多)的方法中执行此操作。 我尝试使用 ExecutorService 及其线程池,但如果我将 ExecutorService 声明为 class 字段并开始向其提交工作,有时它会抛出

java.lang.OutOfMemoryError: unable to create new native thread

所以我决定使用这段代码:

ExecutorService executor = Executors.newFixedThreadPool(2); 

Future<Integer> taskOne = executor.submit(new Callable<Integer> () {
    public Integer call() throws Exception {
        //Do work...
        return 0;
    }
});

Future<Integer> task2 = executor.submit(new Callable<Integer> () {
    public Integer call() throws Exception {
        //Do work...
        return 0;
    }
});

task1.get();
task2.get();

executor.shutdown();

while(!executor.isTerminated());

问题是,与单线程解决方案相比,使用这种新方法的应用程序性能更差。我认为这是由于在每次方法调用时创建新线程池的开销。

所以,我的问题是:有没有一种方法可以完成同样的任务,但不必在每次方法调用时都创建和关闭线程池?

谢谢。

您描述的 class 现场解决方案听起来是一个更好的设计。那个游泳池有多大?您应该调试 OutOfMemoryError 而不是切换到劣质设计。

我不一定会说它的设计本身很差,但有几点需要考虑。就个人而言,我喜欢线程池,如果使用得当,它是一个强大的解决方案。

性能下降的原因是固定池大小为 2 时,一次只能 运行ning 两个线程。有可能您需要更大的数字 - 可能是 10,可能是 100 - 但至少您可以构建它,这样您就不会 运行 内存不足。

也就是说,如果最初的设计 运行 由于创建了太多线程而导致内存不足,您肯定需要限制同时激活的线程数,因此您的性能会受到一些影响。 ..它不需要是全有或全无。

您还可以使用无限执行器线程池,假设 运行ning 线程及时执行 return,这样您仍然不会使线程达到最大值。如果线程 return 以某种确定性的方式存在,当一个线程被 return 加入池时,它可以立即用于下一个可用任务,而无需创建任何东西。所以这很好。

综上所述,查看异常消息,也有可能在操作系统级别您无法创建更多线程,无论您在 Java 内做了什么。我在 CentOS 上有一个服务 运行ning 并且我合法地不得不增加每个进程允许的线程数(在这种情况下,一个 Java 进程 运行ning 我的服务)因为有一个max 和我正在击中它。如果你 运行ning 一些 linux 风格,那也可能是它,特别是因为看起来线程本身除了 returning 什么都不做。