gpt4 book ai didi

java - 在 Java 线程中对集合进行同时读写排序

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

我正在尝试编写代码,看看如果一个线程修改集合而其他线程读取该集合会发生什么。这是代码

package threading;

import java.util.ArrayList;

public class ReadAndWrite {

static ArrayList<Integer> coll = new ArrayList<Integer>();

public static void main(String[] args) {
coll.add(1);
coll.add(3);
coll.add(5);

Thread t = new Thread() {
public void run(){
coll.add(2);
coll.add(6);
coll.add(8);
}
};
Thread t1 = new Thread() {
public void run(){
System.out.println(" collection is "+coll + " and size is "+coll.size());
}
};
Thread t2 = new Thread() {
public void run(){
System.out.println(" collection is "+coll+ " and size is "+coll.size());
}
};
Thread t3 = new Thread() {
public void run(){
System.out.println(" collection is "+coll+ " and size is "+coll.size());
}
};
Thread t4 = new Thread() {
public void run(){
System.out.println(" collection is "+coll+ " and size is "+coll.size());
}
};
Thread t5 = new Thread() {
public void run(){
System.out.println(" collection is "+coll+ " and size is "+coll.size());
}
};
t.start();

t1.start();

t2.start();
t3.start();

t4.start();
t5.start();

}

}

当我首先开始写入线程时,这是我每次得到的响应。

collection is [1, 3, 5, 2, 6, 8] and size is 6
collection is [1, 3, 5, 2, 6, 8] and size is 6
collection is [1, 3, 5, 2, 6, 8] and size is 6
collection is [1, 3, 5, 2, 6, 8] and size is 6
collection is [1, 3, 5, 2, 6, 8] and size is 6

一旦我像下面这样改变顺序,事情就会变得一团糟

 t1.start();
t.start();
t2.start();
t3.start();

t4.start();
t5.start();

回应

 collection is [1, 3, 5] and size is 3
collection is [1, 3, 5, 2, 6, 8] and size is 6
collection is [1, 3, 5, 2, 6, 8] and size is 6
collection is [1, 3, 5] and size is 3
collection is [1, 3, 5] and size is 3

如果我们进一步尝试排序,我们会看到如下错误

Exception in thread "Thread-1"  collection is [1, 3, 5, 2, 6, 8] and size is 6Exception in thread "Thread-2" 
collection is [1, 3, 5, 2, 6, 8] and size is 6
collection is [1, 3, 5, 2, 6, 8] and size is 6
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
at java.util.AbstractCollection.toString(AbstractCollection.java:461)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at threading.ReadAndWrite$3.run(ReadAndWrite.java:28)
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
at java.util.AbstractCollection.toString(AbstractCollection.java:461)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at threading.ReadAndWrite$2.run(ReadAndWrite.java:23)

问题:

  1. 同步或锁定似乎是一个明显的解决方案,但为什么首先启动写入线程会给出统一的结果,线程应该是无序运行的,不是吗?
  2. 我认为同时写入是一个问题,但即使我们只有一个写入线程,我们也会遇到错误,为什么?

非常感谢对上述情况的指导,提前致谢。席德

最佳答案

问题 1 的回答:您关于线程应该无序运行的说法并不准确。几点:1. Java 没有指定线程的实现方式,因此可以使用 native 线程或绿色线程来实现,绿色线程是由 JVM 调度的仅 Java 结构。线程的实现方式可能会影响运行时行为。 Linux 和 Windows 上的 JVM 使用 native 线程。2. 当您启动一个线程时,它会执行一段时间,然后被中断并运行另一个线程。您的线程执行的操作非常少,因此当您运行编写器线程时,它会在调度任何其他线程之前运行完成。

基于上述内容,您不能对线程何时运行以及它们将执行多少条语句做出任何假设,这取决于许多不同的变量,特别是在使用由操作系统调度的 native 线程时。

问题 2 的回答:当您迭代 ArrayList 时,迭代器的 next() 方法会跟踪 modCount。如果通过添加或删除元素来修改集合,则 modCount 将发生变化,并且它将与预期的 modCount 不匹配,因此 Iterator 将抛出 ConcurrentModificationException。因此,即使您只有 1 个写入器,如果您有一个并发读取器,您也会收到 ConcurrentModificationException

CopyOnWriteArrayList是一个线程安全的ArrayList实现

关于java - 在 Java 线程中对集合进行同时读写排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56981520/

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