How to Create a Concurrent List in Java
Concurrency is the process to run programs or functions in a parallel run. When multiple threads work on the same method, it allows a decreased time and an increased throughput.
Java provides the CopyOnWriteArrayList
class that allows an efficient way of List
operations, and the functions work in a thread-safe manner. It means that when two or more threads try to manipulate the list, then the given class allows read-write
operations in a thread-safe way. Internally, when modifying methods of the list interface such as the add
or remove
functions, the content of the CopyOnWriteArrayList
gets copied into the new internal copy. This feature allows it to be thread-safe and allows parallel processing.
The class CopyOnWriteArrayList
is present in the java.util.concurrent
package. Below is a code block example that demonstrates the operations on the given class.
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class ConcurrentListOperations {
public static void main(String[] args) {
List<Integer> temp_list = Arrays.asList(1, 2, 3);
List<Integer> list = new CopyOnWriteArrayList<>(temp_list);
new WriteThread("Writer", list).start();
new ReadThread("Reader", list).start();
}
}
class WriteThread extends Thread {
private final List<Integer> list;
public WriteThread(String name, List<Integer> list) {
this.list = list;
super.setName(name);
}
public void run() {
int count = 4;
int counter = 0;
do {
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
list.add(count++);
System.out.println(super.getName() + " done");
counter++;
} while (counter != 5);
}
}
class ReadThread extends Thread {
private final List<Integer> list;
public ReadThread(String name, List<Integer> list) {
this.list = list;
super.setName(name);
}
public void run() {
while (true) {
StringBuilder output = new StringBuilder("\n" + super.getName() + ":");
for (Integer nextVal : list) {
output.append(" ").append(nextVal);
}
System.out.println(output);
}
}
}
Driver Class in Java
In the program above, three classes are defined. The first one with the main
method is the driver class, and others are there for functioning. In the ConcurrentListOperations
class, the temporary list gets initialized with three integers initially. The temp_list
formed is passed into the CopyOnWriteArrayList
constructor, which is another type of ArrayList
class.
The class initializes the array with the values defined above. Now, the instance of copyOnWriteArrayList
gets passed to the thread classes created previously. This class will only make the list thread-safe; hence, allowing parallel operations on the list instance.
Thread Class in Java
The two thread classes are ReadThread
and WriteThread
. The actual work of the class is to read and write the same list simultaneously. The WriteThread
class extends the Thread
class, which is one way to declare the threads. It has a public constructor that assigns the list instance received to the local variable and initializes the thread name.
The actual business logic for threads is present in their run
method. To start a thread, the start
method is called over the thread class instance that’s newly created.
Use the run
Method in Java
In the run
method of the WriteThread
class, a counter is initialized in the loop condition to track the iterations of the write
class in the run
method. The do-while
loop gets used to keep track count of iteration runs.
Inside the conditional block, the sleep
method of the Thread
class gets called to make the thread sleep for the defined time. The function causes the parallel, executing the thread to sleep for a definite amount of milliseconds. It throws IllegalArgumentException
if the milliseconds passed are negative and InterruptedException
if any thread is interrupted.
The add
method gets used to add elements in the list by concurrent threads. It throws UnsupportedOperationException
if the operation is not allowed by the list instance. On the other hand, it throws ClassCastException
if the class of the specified element is not of the same type of the list. It throws NullPointerException
if the specified value is null and IllegalArgumentException
if some property of this element prevents the element from addition.
Similarly, in the run
method of the ReadThread
class, a constructor is defined; it initializes the name and the list. The run
method has the actual read
logic. The StringBuilder
class gets used to make manipulations in the output. The append
method appends the output found in the write thread class with the existing one.
Hence, the read
and write
operations happen concurrently and get printed in the console in the above format. The write thread sleeps for some 5000 milliseconds, and the writer output will get displayed fewer times compared to the read
thread. The ...
signifies the threads running endlessly and printing the same output because no write
operation has been made. Once the write
process is a success, the read
thread now prints the newly added value.
Output:
Reader: 1 2 3
..
Writer done
Reader: 1 2 3 4
...
Writer done
Reader: 1 2 3 4 5
Rashmi is a professional Software Developer with hands on over varied tech stack. She has been working on Java, Springboot, Microservices, Typescript, MySQL, Graphql and more. She loves to spread knowledge via her writings. She is keen taking up new things and adopt in her career.
LinkedIn