多线程时线程 "main" java.util.ConcurrentModificationException 出现异常
Exception in thread "main" java.util.ConcurrentModificationException while multithreading
我正在开发一个多线程程序,目的是通过三个线程同时在列表中添加 150000 名学生,这意味着每个线程将添加 50000。这是以下程序:
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();
}
}
}
我想做的是从 Main
class 调用方法 threadsL
,将学生列表添加到数据库中,然后计算执行时间的平均值执行 15 次。
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);
}
}
在 Main.java
class 中,我得到以下异常:
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)
第 27 行是:
for(Student e : ThreadsStudents.students) {
basedd.insertTable(e);
}
你能帮我解决这个问题吗?
提前感谢您的帮助!
你的程序几乎没有问题。
在 ThreadStudents 的所有线程完成之前,您的程序正在返回主线程。所以你试图在所有线程都写入之前读取,这就是你得到 concurrentModification exception
的原因
students 是一个 ArrayList 对象,这意味着它不是线程安全的。
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();
}
}
}
}
我的输出完全符合预期,即 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
我正在开发一个多线程程序,目的是通过三个线程同时在列表中添加 150000 名学生,这意味着每个线程将添加 50000。这是以下程序:
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();
}
}
}
我想做的是从 Main
class 调用方法 threadsL
,将学生列表添加到数据库中,然后计算执行时间的平均值执行 15 次。
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);
}
}
在 Main.java
class 中,我得到以下异常:
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)
第 27 行是:
for(Student e : ThreadsStudents.students) {
basedd.insertTable(e);
}
你能帮我解决这个问题吗?
提前感谢您的帮助!
你的程序几乎没有问题。
在 ThreadStudents 的所有线程完成之前,您的程序正在返回主线程。所以你试图在所有线程都写入之前读取,这就是你得到 concurrentModification exception
的原因students 是一个 ArrayList 对象,这意味着它不是线程安全的。
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(); } } } }
我的输出完全符合预期,即 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