- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我们知道ArrayList不是线程安全的,而VectorList是线程安全的。我想制作一个程序来显示操作是在 VectorList 而不是 ArrayList 中同步执行的。我面临的唯一问题是如何?什么样的操作?
例如:- 如果我们向任何列表添加一个值,程序只需添加值即可。
我尝试制作一个,但意识到我的程序的同步性依赖于变量 j,而不是 ArrayList 或 VectorList。
public class ArrayDemo implements Runnable {
private static ArrayList<Integer> al = new ArrayList<Integer>();
Random random = new Random();
int j = 0;
public void run() {
while ( j < 10) {
int i = random.nextInt(10);
al.add(i);
System.out.println(i + " "+ Thread.currentThread().getName());
j++;
//System.out.println(al.remove(0));
}
}
public static void main(String[] args) {
ArrayDemo ad = new ArrayDemo();
Thread t = new Thread(ad);
Thread t1 = new Thread(ad);
t.start();t1.start();
}
}
最佳答案
小测试程序:
public class Test extends Thread {
public static void main(String[] args) throws Exception {
test(new Vector<>());
test(new ArrayList<>());
test(Collections.synchronizedList(new ArrayList<>()));
test(new CopyOnWriteArrayList<>());
}
private static void test(final List<Integer> list) throws Exception {
System.gc();
long start = System.currentTimeMillis();
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.length; i++)
threads[i] = new Test(list);
for (Thread thread : threads)
thread.start();
for (Thread thread : threads)
thread.join();
long end = System.currentTimeMillis();
System.out.println(list.size() + " in " + (end - start) + "ms using " + list.getClass().getSimpleName());
}
private final List<Integer> list;
Test(List<Integer> list) {
this.list = list;
}
@Override
public void run() {
try {
for (int i = 0; i < 10000; i++)
this.list.add(i);
} catch (Exception e) {
e.printStackTrace(System.out);
}
}
}
示例输出
100000 in 16ms using Vector
java.lang.ArrayIndexOutOfBoundsException: 466
at java.util.ArrayList.add(ArrayList.java:459)
at Test.run(Test.java:36)
java.lang.ArrayIndexOutOfBoundsException: 465
at java.util.ArrayList.add(ArrayList.java:459)
at Test.run(Test.java:36)
java.lang.ArrayIndexOutOfBoundsException: 10
at java.util.ArrayList.add(ArrayList.java:459)
at Test.run(Test.java:36)
32507 in 15ms using ArrayList
100000 in 16ms using SynchronizedRandomAccessList
100000 in 3073ms using CopyOnWriteArrayList
如您所见, Vector
它正常完成并返回 100000
,这是在 10 个并行线程中添加 10000 个值后的预期大小。
与 ArrayList
您会看到两种不同的失败:
ArrayIndexOutOfBoundsException
而终止在调用 add()
的电话中.70000
值,但列表仅包含 32507
值,所以很多附加值都丢失了。第三个测试,使用 Collections.synchronizedList()
,类似于 Vector
.
第四次测试,使用并发 CopyOnWriteArrayList
,也会生成正确的结果,但由于过度复制,速度要慢得多。但是,如果列表较小且很少更改,但经常读取,则它会比同步访问更快。
如果您需要迭代列表,它特别好,因为即使 Vector
和synchronizedList()
将会失败并显示 ConcurrentModificationException
如果列表在迭代时被修改,则 CopyOnWriteArrayList
将迭代列表的快照。
出于好奇,我查了一些 Deque
也实现了:
test(new ArrayDeque<>());
test(new ConcurrentLinkedDeque<>());
test(new LinkedBlockingDeque<>());
示例输出
34295 in 0ms using ArrayDeque
100000 in 15ms using ConcurrentLinkedDeque
100000 in 16ms using LinkedBlockingDeque
如您所见,不同步的 ArrayDeque
显示“丢失值”症状,尽管它不会因异常而失败。
两个并发实现, ConcurrentLinkedDeque
和 LinkedBlockingDeque
,工作又好又快。
关于java - 如何显示java arraylist的不同步性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39712360/
我是一名优秀的程序员,十分优秀!