MultiThreading Vs ThreadPoolExecutor

14,123

Solution 1

A ThreadPoolExecutor is just a high level API that enables you to run tasks in multiple threads while not having to deal with the low level Thread API. So it does not really make sense to differentiate between multithreading and ThreadPoolExecutor.

There are many flavours of ThreadPoolExecutors, but most of them allow more than one thread to run in parallel. Typically, you would use an Executor Service and use the Executors factory.

For example, a ExecutorService executor = Executors.newFixedThreadPool(10); will run the tasks you submit in 10 threads.

Solution 2

ThreadPoolExecutor is one way of doing multithreading. It's typically used when you

  1. have independent operations that don't require coordination (though nothing prevents you from coordinating, but you have to be careful)
  2. want to limit the capacity of how many operations you're executing at once, and (optionally) want to queue operations when for execution if the pool is currently working in all threads.

Java 7 has another built in class called a ForkJoinPool which is typically used for Map-Reduce type operations. For instance, one can imagine implementing a merge sort using a ForkJoinPool by splitting the array in 1/2 at each fork point, waiting for the results, and merging the results together.

Solution 3

Thread pools (executors) are one form of multithreading, specifically an implementation of the single producer - multiple consumer pattern, in which a thread repeatedly puts work in a queue for a team of worker threads to execute. It is implemented using regular threads and brings several benefits:

  • thread anonymity - you don't explicitly control which thread does what; just fire off tasks and they'll be handled by the pool.
  • it encapsulates a work queue and thread team - no need to bother implementing you own thread-safe queue and looping threads.
  • load-balancing - since workers take new tasks as they finish previous ones, work is uniformly distributed, provided there is a sufficiently large number of tasks available.
  • thread recycling - just create a single pool at the beginning an keep feeding it tasks. No need to keep starting and killing threads every time work needs to be done.

Given the above, it is true that pools are suited for tasks that are usually independent of each-other and usually short-lived (long I/O operations will just tie up threads from the pool that won't be able to do other tasks).

Solution 4

ThreadPoolExecutor is a form of multithreading, with a simpler API to use than directly using Threads, where you submit tasks indeed. However, tasks can submit other tasks, so they need not be independent. As for the division of tasks into sub-tasks, you may be thinking of the new fork/join API in JDK7.

Solution 5

From source code documentation of 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 is one way of achieving concurrency. There are many ways in achieving concurrency :

Executors framework provides different APIs. Some of important APIs are listed below.

static ExecutorService  newFixedThreadPool(int nThreads)

Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue.

static ExecutorService  newCachedThreadPool()

Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available.

static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically.

static ExecutorService  newWorkStealingPool()

Creates a work-stealing thread pool using all available processors as its target parallelism level.

Have a look at below SE questions:

java Fork/Join pool, ExecutorService and CountDownLatch

How to properly use Java Executor?

Share:
14,123
Pit Digger
Author by

Pit Digger

Updated on June 23, 2022

Comments

  • Pit Digger
    Pit Digger almost 2 years

    I have used multithreading in many of applications I wrote . While reading more I came across ThreadPoolExecutors. I couldn't not differentiate between the two scenario wise .

    Still what I understand is I should use multithreading when I have a task I want to divide a task in to multiple small tasks to utilize CPU and do the work faster . And use ThreadPoolExecutor when I have a set to tasks and each task can be run independent of each other.

    Please correct me if I am wrong . Thanks