多线程 vs 线程池执行器 (ThreadPoolExecutor)

11

我在写的许多应用程序中都使用了多线程技术。在阅读更多相关资料时,我接触到了ThreadPoolExecutors技术。就场景而言,我不能区分这两种方式。

但是,我理解的是,当我有一个任务需要分成多个小任务来利用CPU以加快工作速度时,应该使用多线程技术。如果我有一组任务,并且每个任务可以独立运行,则应该使用ThreadPoolExecutor技术。

如果我理解有误,请您指正。谢谢!


1
这也是我的理解。对于独立线程,请使用ThreadPoolExecutor,而对于分治方法,请使用Multithread。 - gtgaxiola
5个回答

22
一个ThreadPoolExecutor只是一个高级API,允许你在多线程中运行任务,而不需要处理底层Thread API。因此,区分多线程和ThreadPoolExecutor并没有太多意义。
有许多种ThreadPoolExecutor,但大多数都允许多个线程并发运行。通常,您会使用Executor Service并使用Executors工厂。
例如,ExecutorService executor = Executors.newFixedThreadPool(10); 将在10个线程中运行您提交的任务。

11

ThreadPoolExecutor是一种进行多线程操作的方式。通常在以下情况下使用:

  1. 有独立的操作,不需要协调(尽管没有什么可以阻止您进行协调,但必须小心)
  2. 希望限制每次执行操作的能力,并且(可选)希望在池当前正在所有线程中工作时将操作排队等待执行。

Java 7还有另一个内置类称为ForkJoinPool,通常用于Map-Reduce类型的操作。例如,可以使用ForkJoinPool实现归并排序,通过在每个分支点将数组分成一半,等待结果,然后将结果合并在一起。


9
线程池(执行器)是多线程的一种形式,特别是单生产者-多消费者模式的实现,其中一个线程重复将工作放入队列中供团队工人线程执行。它使用常规线程实现,并带来了几个好处:
  • 线程匿名性 - 您不需要明确控制哪个线程执行什么任务;只需启动任务即可由线程池处理。
  • 它封装了工作队列和线程组 - 不需要自己实现线程安全队列和循环线程。
  • 负载平衡 - 由于工人在完成先前的任务后接受新任务,因此工作得到均匀分配,只要有足够大量的任务可用。
  • 线程回收 - 只需在开始时创建一个线程池并不断提供任务即可。无需每次需要完成工作时都启动和终止线程。
鉴于上述内容,可以得出结论,线程池适用于通常彼此独立且通常寿命较短的任务(长时间的I/O操作会占用线程池中的线程,这些线程将无法执行其他任务)。

1

ThreadPoolExecutor是一种多线程形式,具有比直接使用Threads更简单的API,您可以提交任务。但是,任务可以提交其他任务,因此它们不需要是独立的。至于将任务划分为子任务,您可能会考虑JDK7中的新fork/join API。


0

来自ThreadPoolExecutor的源代码文档

/*
 * <p>Thread pools address two different problems: they usually
 * provide improved performance when executing large numbers of
 * asynchronous tasks, due to reduced per-task invocation overhead,
 * and they provide a means of bounding and managing the resources,
 * including threads, consumed when executing a collection of tasks.
 * Each {@code ThreadPoolExecutor} also maintains some basic
 * statistics, such as the number of completed tasks.
 *
 * <p>To be useful across a wide range of contexts, this class
 * provides many adjustable parameters and extensibility
 * hooks. However, programmers are urged to use the more convenient
 * {@link Executors} factory methods {@link
 * Executors#newCachedThreadPool} (unbounded thread pool, with
 * automatic thread reclamation), {@link Executors#newFixedThreadPool}
 * (fixed size thread pool) and {@link
 * Executors#newSingleThreadExecutor} (single background thread), that
 * preconfigure settings for the most common usage
 * scenarios.
 */

ThreadPoolExecutor是实现并发的一种方式。有许多实现并发的方式:

Executors框架提供了不同的API。下面列出了一些重要的API。

static ExecutorService  newFixedThreadPool(int nThreads)

创建一个线程池,该线程池重用一定数量的线程,这些线程从共享的无界队列中运行。
static ExecutorService  newCachedThreadPool()

创建一个线程池,按需创建新的线程,但会在可用时重复使用先前构建的线程。

static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

创建一个线程池,可以安排命令在给定延迟后运行,或定期执行。
static ExecutorService  newWorkStealingPool()

创建一个工作窃取线程池,使用所有可用的处理器作为目标并行级别。

请查看下面的SE问题:

Java Fork/Join pool,ExecutorService和CountDownLatch

如何正确使用Java Executor?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接