首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java中线程集合的同时读写排序

问Java中线程集合的同时读写排序
EN

Stack Overflow用户
提问于 2019-07-11 04:10:58
回答 1查看 44关注 0票数 0

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

代码语言:javascript
复制
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();

        }

        }

当我开始写线程首先,这是我得到的所有时间的响应。

代码语言:javascript
复制
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

一旦我像下面一样改变了订单,事情就会变得混乱起来。

代码语言:javascript
复制
 t1.start();
t.start();
t2.start();
t3.start();

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

响应

代码语言:javascript
复制
 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

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

代码语言:javascript
复制
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. 我认为同步写作是一个问题,但是即使我们只有一个写线程,我们也会遇到错误,为什么呢?

将非常感谢您对上述方案的指导,谢谢。侧边

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-07-11 09:32:32

对问题1的回答:你所说的线程应该乱七八糟的说法并不准确。有几点: 1. Java没有指定线程是如何实现的,因此可以使用本机线程或绿色线程来实现线程,绿色线程是Java仅由JVM调度的构造。如何实现线程可能会影响运行时行为。Linux和Windows上的JVM使用本机线程。2.当启动一个线程时,它执行一段时间,然后被中断,另一个线程运行。您的线程所做的非常少,以至于当您运行写入线程时,它会在调度其他线程之前运行到完成。

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

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

CopyOnWriteArrayList是线程安全的ArrayList实现。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56981520

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档