集合类与多线程

非线程安全的java.util.ArrayList类

Main.java

1
2
3
4
5
6
7
8
9
10
11
import java.util.ArrayList;
import java.util.List;

public class Main {

public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
new WriterThread(list).start();
new ReaderThread(list).start();
}
}

WriterThread.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.List;

public class WriterThread extends Thread {
private final List<Integer> list;

public WriterThread(List<Integer> list) {
super("WriterThread");
this.list = list;
}

public void run() {
for (int i = 0; ; i++) {
list.add(i);
list.remove(0);
}
}
}

ReaderThread.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.List;

public class ReaderThread extends Thread {
private final List<Integer> list;

public ReaderThread(List<Integer> list) {
super("ReaderThread");
this.list = list;
}

public void run() {
while (true) {
for (int n : list) {
System.out.println(n);
}
}
}
}

result

1
2
3
4
Exception in thread "ReaderThread" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at ReaderThread.run(ReaderThread.java:13)

利用Collections.synchronizedList方法所进行的同步

Main.java

1
2
3
4
5
6
7
8
9
10
11
12
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {

public static void main(String[] args) {
final List<Integer> list = Collections.synchronizedList(new ArrayList<>());
new WriterThread(list).start();
new ReaderThread(list).start();
}
}

ReaderThread.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.List;

public class ReaderThread extends Thread {
private final List<Integer> list;

public ReaderThread(List<Integer> list) {
super("ReaderThread");
this.list = list;
}

public void run() {
while (true) {
synchronized(list) {
for (int n : list) {
System.out.println(n);
}
}
}
}
}

使用copy-on-write的java.util.concurrent.CopyOnWriteArrayList类

Main.java

1
2
3
4
5
6
7
8
9
10
11
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class Main {

public static void main(String[] args) {
final List<Integer> list = new CopyOnWriteArrayList<>();
new WriterThread(list).start();
new ReaderThread(list).start();
}
}

比较

使用copy-on-write时,每次执行“写”操作都会执行复制。因此,程序频繁执行“写”操作时,如果使用CopyOnWriteArrayList,会比较花费时间。但如果写操作比较少,而读操作频率非常高时,使用CopyOnWriteArrayList是非常棒的。