I am developing a multithreaded program with the intention of adding 150000 students in a list at the same time by three threads, which means each of them will add 50000. Here is the following program:
public class ThreadsStudents implements Runnable {
public static List<Student> students = new ArrayList<>();
@Override
public void run() {
for(int i = 0; i < 50000; i++) {
students.add(Generator.generetorStudent());
}
}
public static void threadsL(int nbThreads) {
ArrayList<Thread> th = new ArrayList<>();
for(int i = 0; i < nbThreads; i++) {
th.add(new Thread(new ThreadsStudents()));
}
for(Thread threads: th) {
threads.start();
}
}
}
What I am trying to do is to call the method threadsL
from Main
class, add the list of students in a database and then do an average of the execution time for 15 executions.
public class Main {
public static void main(String[] argv) {
long startDate,endDate;
double measure;
double average = 0;
ManipulationBDD basedd = new ManipulationBDD();
for (int i = 0; i < 15; i++) {
startDate = System.nanoTime();
ThreadsStudents.threadsL(3);
for(Student e : ThreadsStudents.students) {
basedd.insertTable(e);
}
endDate = System.nanoTime();
measure = (double) (endDate - startDate) / 1000000000;
average = average + measure;
basedd.empty();
}
average = average / 15;
System.out.println("The average is : " + average);
}
}
In the Main.java
class, I get the following Exception:
Exception in thread "main" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1043)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:997)
at Main.main(Main.java:27)
Line 27 is:
for(Student e : ThreadsStudents.students) {
basedd.insertTable(e);
}
Can you help me with this?
Thank you in advance for your help !
There are few problems with your program.
Your program is coming back to main thread before all the threads of ThreadStudents are finished. So you are trying to read before all the threads have written, which is why you are getting concurrentModification exception
students is a ArrayList object which means it is not thread safe.
public class Main {
public static void main(String[] argv) {
for (int i = 0; i < 1; i++) {
ThreadStudents.threadsL(3);
System.out.println(ThreadStudents.students.size());
}
}
}
public class ThreadStudents implements Runnable {
public static List<Integer> students = new CopyOnWriteArrayList<>();
// Thread safe version of array list
@Override
public void run() {
System.out.println("Starting: " + Thread.currentThread().getName());
for(int i = 0; i < 50000; i++) {
students.add(1);
}
System.out.println("Ending " + Thread.currentThread().getName());
}
public static void threadsL(int nbThreads) {
ExecutorService executor = Executors.newFixedThreadPool(nbThreads);
// creates fixed number of threads
for(int i = 0; i < nbThreads; i++) {
executor.execute(new ThreadStudents());
// executor services will call run() from each thread
}
executor.shutdown(); // tell the service that no new threads can be submitted
while(true) {
try {
if (executor.awaitTermination(5, TimeUnit.MINUTES)) break;
// it will wait till all the threads have finished or Max 5 mins
// before going back to main thread
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
My output is exactly as expected which is 150,000.
Starting: pool-1-thread-3
Starting: pool-1-thread-1
Starting: pool-1-thread-2
Ending pool-1-thread-3
Ending pool-1-thread-1
Ending pool-1-thread-2
150000