Core Java

Java 8 Parallel Streams Example

Hello readers, Parallel Streams are the greatest addition to Java8 after Lambdas. This tutorial explains the parallel streams concept in detail.

1. Introduction

The Stream API enables developers to create the parallel streams that can take advantage of multi-core architectures and enhance the performance of Java code. In a parallel stream, the operations are executed in parallel and there are two ways to create a parallel stream.

  • Using the parallelStream() method on a collection
  • Using the parallel() method on a stream

E.g.

Optional<Integer> calcProd = list1.parallelStream().reduce((a,b) -> a*b));

In this code, a parallel stream is obtained from the list1 and the reduction operation is performed on it.

Do remember, Parallel Streams must be used only with stateless, non-interfering, and associative operations i.e.

  • A stateless operation is an operation in which the state of one element does not affect another element
  • A non-interfering operation is an operation in which data source is not affected
  • An associative operation is an operation in which the result is not affected by the order of operands

1.1 Parallel Streams in Java 8

Let’s take a scenario where you have a list of employee objects and you have to count the employees whose salary is above 15000. Generally, to solve this problem you will iterate over list going through each employee and checking if employee’s salary is above 15000. This takes O(N) time since you go sequentially.

Streams give us the flexibility to iterate over the list in a parallel pattern and can give the total in quick fashion. Stream implementation in Java is by default sequential unless until it is explicitly mentioned in parallel. When a stream executes in parallel, the Java runtime partitions the stream into multiple sub-streams. Aggregate operations iterate over and process these sub-streams in parallel and then combine the results.

Fig. 1: Sequential vs. Parallel Streams in Java8
Fig. 1: Sequential vs. Parallel Streams in Java8

The only thing to keep in mind to create parallel stream is to call the parallelStream() method on the collection else by default the sequential stream gets returned by stream() method.

1.1.1 Parallel Streams Performance Implications

Parallel Stream has equal performance impacts as like its advantages.

  • Since each sub-stream is a single thread running and acting on the data, it has overhead compared to the sequential stream
  • Inter-thread communication is dangerous and takes time for coordination

1.2 When to use Parallel Streams?

  • They should be used when the output of the operation is not needed to be dependent on the order of elements present in source collection (i.e. on which the stream is created)
  • Parallel Streams can be used in case of aggregate functions
  • Parallel Streams quickly iterate over the large-sized collections
  • Parallel Streams can be used if developers have performance implications with the Sequential Streams
  • If the environment is not multi-threaded, then Parallel Stream creates thread and can affect the new requests coming in

Now, open up the Eclipse Ide and I will explain further the parallel streams in Java8 programming.

2. Java8 Parallel Streams Example

2.1 Tools Used

We are using Eclipse Oxygen, JDK 1.8 and Maven.

2.2 Project Structure

Firstly, let’s review the final project structure, in case you are confused about where you should create the corresponding files or folder later!

Fig. 2: Application Project Structure
Fig. 2: Application Project Structure

2.3 Project Creation

This section will show on how to create a Java-based Maven project with Eclipse. In Eclipse IDE, go to File -> New -> Maven Project.

Fig. 3: Create Maven Project
Fig. 3: Create Maven Project

In the New Maven Project window, it will ask you to select project location. By default, ‘Use default workspace location’ will be selected. Select the ‘Create a simple project (skip archetype selection)’ checkbox and just click on next button to go ahead.

Fig. 4: Project Details
Fig. 4: Project Details

It will ask you to ‘Enter the group and the artifact id for the project’. We will input the details as shown in the below image. The version number will be by default: 0.0.1-SNAPSHOT.

Fig. 5: Archetype Parameters
Fig. 5: Archetype Parameters

Click on Finish and the creation of a maven project is completed. If you see, it has downloaded the maven dependencies and a pom.xml file will be created. It will have the following code:

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>Java8ParallelStream</groupId>
	<artifactId>Java8ParallelStream</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>
</project>

Developers can start adding the dependencies that they want. Let’s start building the application!

3. Application Building

Below step is involved in developing this application.

3.1 Java Class Implementation

Let’s create the required Java file. Right-click on the src/main/java folder, New -> Package.

Fig. 6: Java Package Creation
Fig. 6: Java Package Creation

A new pop window will open where we will enter the package name as: com.jcg.java.

Fig. 7: Java Package Name (com.jcg.java)
Fig. 7: Java Package Name (com.jcg.java)

Once the package is created in the application, we will need to create the implementation class to illustrate the Java8 Parallel Stream example. Right-click on the newly created package: New -> Class.

Fig. 8: Java Class Creation
Fig. 8: Java Class Creation

A new pop window will open and enter the file name as: ParallelStreamDemo. The implementation class will be created inside the package: com.jcg.java.

Fig. 9: Java Class (ParallelStreamDemo.java)
Fig. 9: Java Class (ParallelStreamDemo.java)

3.1.1 Example on Parallel Streams

Here is an example of Parallel Streams where we have created a list of 600 employees out of which there are 300 employees whose salary is above 15000. Let’s see the simple code snippet that shows this implementation.

ParallelStreamDemo.java

package com.jcg.java;

import java.util.ArrayList;
import java.util.List;

public class ParallelStreamDemo {

	public static void main(String[] args) {

		long t1, t2;
		List<Employee> eList = new ArrayList<Employee>();
		for(int i=0; i<100; i++) {
			eList.add(new Employee("A", 20000));
			eList.add(new Employee("B", 3000));
			eList.add(new Employee("C", 15002));
			eList.add(new Employee("D", 7856)); 
			eList.add(new Employee("E", 200)); 
			eList.add(new Employee("F", 50000));
		}

		/***** Here We Are Creating A 'Sequential Stream' & Displaying The Result *****/
		t1 = System.currentTimeMillis();   
		System.out.println("Sequential Stream Count?= " + eList.stream().filter(e -> e.getSalary() > 15000).count());

		t2 = System.currentTimeMillis();
		System.out.println("Sequential Stream Time Taken?= " + (t2-t1) + "\n");

		/***** Here We Are Creating A 'Parallel Stream' & Displaying The Result *****/
		t1 = System.currentTimeMillis();		
		System.out.println("Parallel Stream Count?= " + eList.parallelStream().filter(e -> e.getSalary() > 15000).count());

		t2 = System.currentTimeMillis();
		System.out.println("Parallel Stream Time Taken?= " + (t2-t1));
	}
}

4. Run the Application

To run the application, developers need to right-click on the class, Run As -> Java Application. Developers can debug the example and see what happens after every step!

Fig. 10: Run Application
Fig. 10: Run Application

5. Project Demo

The application shows the following logs as output where creating a Sequential Stream and filtering elements took 178 ms, whereas Parallel Stream only took 15 ms.

# Logs for 'SEQUENTIAL STREAM' #
=============================
Sequential Stream Count?= 300
Sequential Stream Time Taken?= 178

# Logs for 'PARALLEL STREAM' #
===========================
Parallel Stream Count?= 300
Parallel Stream Time Taken?= 15 

That’s all for this post. Happy Learning!

6. Conclusion

That’s all for Java8 Parallel Streams example and developers can use it to divide the provided task into many and run them in different threads. I hope this article served you whatever you were looking for.

7. Download the Eclipse Project

This was an example of Parallel Streams in Java8.

Download
You can download the full source code of this example here: Java8ParallelStream

Yatin

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

9 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Seymour
5 years ago

Really do like the functionality of Java 8 streams. I have been able to do some of the same tasks with streams that I was doing prior to Java 8 with a lot less lines of code.

Anon
Anon
5 years ago

The “time taken” measurements do not show anything. Try to do the parallel stream first, and the times are completely different.

Hossam
Hossam
5 years ago
Reply to  Anon

The processor is caching that operation so even if you tried to do the parallel stream first, will get the same result and maybe the sequential would be faster

tama
tama
4 years ago
Reply to  Hossam

yeah but processor is limited to caching that operation , if u have more thank 1 operation and complexity. it will be take a time if u used sequential. remember 1 people will take a long time than 2 people .its princip.

Prashant
Prashant
3 years ago

How to know the number of threads used and can we control that?

SArat
SArat
3 years ago

Thanks a lot is too good. u write excellent content.

Boopathi
Boopathi
3 years ago

Try below code and give me your comments.  public static void main(String[] args)    {     long t1, t2;     List<Employee> eList = new ArrayList<Employee>();     for(int i=0; i<100; i++) {       eList.add(new Employee(“A”, 20000));       eList.add(new Employee(“B”, 3000));       eList.add(new Employee(“C”, 15002));       eList.add(new Employee(“D”, 7856));        eList.add(new Employee(“E”, 200));        eList.add(new Employee(“F”, 50000));     }              /***** Here We Are Creating A ‘Parallel Stream’ & Displaying The Result *****/     t1 = System.currentTimeMillis();          System.out.println(“Parallel Stream Count?= ” + eList.parallelStream().filter(e -> e.getSalary() > 15000).count());       t2 = System.currentTimeMillis();     System.out.println(“Parallel Stream Time Taken?= ” + (t2-t1));           /***** Here We Are Creating A ‘Sequential Stream’ & Displaying The Result *****/… Read more »

Back to top button