gpt4 book ai didi

java - 如何显示java arraylist的不同步性?

转载 作者:行者123 更新时间:2023-12-02 03:20:16 29 4
gpt4 key购买 nike

我们知道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() 的电话中.
  • 即使三个失败的线程立即终止,在添加任何内容之前,其他 7 个线程仍应分别添加 10000 个值,总共 70000值,但列表仅包含 32507值,所以很多附加值都丢失了。

第三个测试,使用 Collections.synchronizedList() ,类似于 Vector .

第四次测试,使用并发 CopyOnWriteArrayList ,也会生成正确的结果,但由于过度复制,速度要慢得多。但是,如果列表较小且很少更改,但经常读取,则它会比同步访问更快。
如果您需要迭代列表,它特别好,因为即使 VectorsynchronizedList()将会失败并显示 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/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com