0%

CopyOnWriteArrayList

CopyOnWriteArrayList

并发容器;增删改加锁,拷贝一份做操作,操作完成后原引用指向拷贝出来的这个对象;读操作不加锁,读的是原容器的数据;保证数据最终一致性,不保证数据实时一致性。
应用场景:多读少写,黑白名单配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package copyonwrite;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* Created by dingxiangyong on 2016/3/26.
*/
public class Test {
/**
* 结束标识
*/
static volatile boolean stopFlag = false;

public static void main(String[] args) {

CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<Integer>();
//初始化集合
for (int i = 0; i < 100000; i++) {
list.add(i);
}

ReadTask readTask1 = new ReadTask(list);
ReadTask readTask2 = new ReadTask(list);
ReadTask readTask3 = new ReadTask(list);
ReadTask readTask4 = new ReadTask(list);

WriteTask writeTask = new WriteTask(list);

ExecutorService service = Executors.newFixedThreadPool(5);
service.execute(readTask1);
service.execute(readTask2);
service.execute(readTask3);
service.execute(readTask4);
service.execute(writeTask);

service.shutdown();
}
}

/**
* 读线程
*/
class ReadTask implements Runnable {

private List<Integer> list;

public ReadTask(List<Integer> list) {
this.list = list;
}


@Override
public void run() {
while (!Test.stopFlag) {
try {
int index = (int) (Math.random() * list.size());
Integer value = list.get(index);
System.out.println("正在读取值:" + value);
Thread.sleep(10); //模拟耗时操作
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

/**
* 写线程
*/
class WriteTask implements Runnable {

private List<Integer> list;

public WriteTask(List<Integer> list) {
this.list = list;
}


@Override
public void run() {
List<Integer> newList = new ArrayList<Integer>();

for (int i = 100000; i < 2000000; i++) {
newList.add(i);
}

try {
Thread.sleep(100); //模拟耗时操作,让读线程可以读到
System.out.println("准备写入copyonwritelist");
list.addAll(newList);
System.out.println("写入copyonwritelist完毕");
Thread.sleep(2000); //模拟耗时操作,让读线程可以读到
Test.stopFlag = true;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}


运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
....
正在读取值:79029
正在读取值:29270
正在读取值:61694
正在读取值:3373
正在读取值:33155
正在读取值:78532
正在读取值:12583
正在读取值:2778
正在读取值:32738
正在读取值:82363
准备写入copyonwritelist
正在读取值:61661
正在读取值:5817
正在读取值:84120
正在读取值:43250
写入copyonwritelist完毕
正在读取值:1744710
正在读取值:422552
正在读取值:1038943
正在读取值:1229489
正在读取值:200887
正在读取值:1547701
正在读取值:1841575
正在读取值:1785725
...

从如上结果可以看出,在写入数据的时候,读取操作并没有被终止,写入完毕后读取操作可以读取到最新的数据。