Why Java 8 Parallel Streams Can Be Slower Than Simple Loops
A production incident shows that using Java 8 parallel streams for message processing can dramatically reduce throughput, making them slower than a straightforward for‑loop due to the shared ForkJoinPool and thread‑pool sizing issues.
Parallel Stream Speed: Not Always Faster?
Java 8 introduced parallel streams as a convenient way to run multithreaded operations with a single line of code. However, a real production incident showed that using parallel streams in a message‑processing handler caused a dramatic drop in consumption capacity, leading to message backlog.
Parallel Stream Implementation Details
The slowdown originates from the way parallel streams use a common ForkJoinPool. All actions submitted to a parallel stream are processed by this shared pool, regardless of the size of any external thread pool.
void testParallelStream() throws InterruptedException {
ExecutorService threadPool = new ThreadPoolExecutor(50, 200,
20, TimeUnit.MINUTES, new ArrayBlockingQueue<>(1000),
new ThreadFactoryBuilder().setNameFormat("test-parallel-thread").build(),
new ThreadPoolExecutor.CallerRunsPolicy());
// for‑loop version
for (int i = 0; i < ARRAY_LENGTH; i++) {
CommonExecutor commonExecutor = new CommonExecutor();
commonExecutor.array = arrays[i];
threadPool.submit(commonExecutor);
}
commonCountDownLatch.await();
// parallel‑stream version
for (int i = 0; i < ARRAY_LENGTH; i++) {
ParallelStreamExecutor parallelStreamExecutor = new ParallelStreamExecutor();
parallelStreamExecutor.array = arrays[i];
threadPool.submit(parallelStreamExecutor);
}
parallelCountDownLatch.await();
}The two executors are:
@Data
private static class CommonExecutor implements Runnable {
private long[] array;
@Override
public void run() {
for (int i = 0; i < array.length; i++) {
array[i] = i * i;
}
commonCountDownLatch.countDown();
}
} @Data
private static class ParallelStreamExecutor implements Runnable {
private long[] array;
@Override
public void run() {
IntStream.range(0, array.length).parallel()
.forEach(i -> array[i] = i * i);
parallelCountDownLatch.countDown();
}
}Running both versions ten times on a two‑dimensional array showed that the for‑loop averaged 16 ms while the parallel stream averaged 46 ms, proving the parallel version was slower.
Why Parallel Streams Can Be Slower
Parallel streams submit tasks to the common ForkJoinPool, whose size defaults to the number of available processors minus one. In the example, the parallel version used only seven threads, whereas the manual thread pool provided up to one hundred threads, leading to a large performance gap.
The common pool is created by ForkJoinPool.makeCommonPool(), which reads system properties to configure parallelism, thread factory, and exception handler. Its default parallelism equals the number of CPU cores minus one, and external threads may also help execute subtasks, which can be problematic when global thread‑local state is involved.
Key Pitfalls
All parallel‑stream tasks in the same JVM share the common pool, which can reduce concurrency in a multithreaded environment.
The common pool size is limited and may interact poorly with ThreadLocal variables, causing accidental cleanup of thread‑local data.
Parallel streams are designed for CPU‑bound work; using them for I/O‑heavy operations such as RPC calls can block pool threads and degrade performance.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Backend Technology
Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
