【问题标题】:Multiple newSingleThreadExecutor vs. newFixedThreadPool of ExecutorServiceExecutorService 的多个 newSingleThreadExecutor vs. newFixedThreadPool
【发布时间】:2016-07-23 17:29:02
【问题描述】:

在我的应用程序中,我有 4 个不同的进程,它们会以一些小停顿永久运行。

当前版本的代码在单独的老式线程中执行每个进程:

Thread nlpAnalyzer = new Thread(() -> {

    // infine lop for auto restore in case of crash
    //noinspection InfiniteLoopStatement
    while (true) {
        try {
            // this method should run permanently, pauses implemented internally
            NLPAnalyzer.analyzeNLP(dbCollection);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
});

nlpAnalyzer.setName("im_nlpAnalyzer");
nlpAnalyzer.start();

现在我想使用ExecutorService 重构这段代码。为此,我至少可以使用两种方法:

  • newFixedThreadPool(numOfProc);
  • numOfProc * newSingleThreadExecutor()

我的问题:

  1. 有什么理由让我更喜欢一个选项而不是另一个选项?
  2. 用 X 线程生成线程池或生成 X newSingleThreadExecutors 更接受什么?
  3. 每种方法的优缺点?

【问题讨论】:

  • 选项 1 更常见且开销最小。
  • 另一方面,您可以将无限循环内的代码重写为Runnable,在运行时将其自身再次发布为执行程序服务。这样,多个任务甚至可以在一个线程上运行。

标签: java multithreading concurrency threadpool executorservice


【解决方案1】:

除了关闭单个执行者之外,我认为以下选项没有任何好处。

numOfProc * newSingleThreadExecutor()

但是你有更多的选择。我更喜欢Executors 的以下三个选项之一。

newFixedThreadPool
newCachedThreadPool
newWorkStealingPool

有关相关查询,请参阅以下 SE 问题:

Java's Fork/Join vs ExecutorService - when to use which?

How to properly use Java Executor?

Difference between Executors.newFixedThreadPool(1) and Executors.newSingleThreadExecutor()

【讨论】:

    【解决方案2】:

    鉴于每个任务都是一个无限循环,我将使用的是一个

    newCachedThreadPool();
    

    这将为每个需要它的任务创建一个线程(仅此而已)

    使用单个线程池的好处是您可以单独关闭池,或为每个线程命名,但如果您不需要,这只是开销。

    注意:您可以使用 setName("My task") 更改线程的名称,这可能对调试/分析目的有用。

    使用 ExecutorService 的技巧之一是它捕获任何未捕获的异常/错误并将其放置在返回的 Future 对象中。通常Future 会被丢弃,这意味着如果您的任务意外终止,它也可能会默默执行。

    我建议您在循环外执行 try/catch(Throwable) 并记录它,以便查看线程是否会意外终止。例如 OutOfMemoryError

    【讨论】:

    • 据我所知,我甚至可以将单独的线程名称分配给newFixedThreadPool,而不仅仅是newSingleThreadExecutor。为 X 线程定义 1 newFixedThreadPool 或 X newSingleThreadExecutors 之间是否存在性能差异?
    • @MikeB。您可以分配一个单独的线程名称,但不能根据任务的目的分配一个可能更有用的名称。无论您选择哪种解决方案,我都会做任何您认为更清楚的事情,Thread 仍然可以工作。
    猜你喜欢
    • 2016-05-07
    • 2013-04-14
    • 1970-01-01
    • 2019-02-17
    • 1970-01-01
    • 1970-01-01
    • 2016-08-08
    • 2010-09-29
    • 2015-01-12
    相关资源
    最近更新 更多