Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java与同步链表_Java_Multithreading_Collections_Synchronization - Fatal编程技术网

Java与同步链表

Java与同步链表,java,multithreading,collections,synchronization,Java,Multithreading,Collections,Synchronization,我必须回答你的问题。第一个问题是为什么我们运行这个函数时会出现ConcurrentModificationException public static void testList() { List<String> list = new ArrayList<String>(); list.add("str3"); for (String st : list) { if (st.equalsIgnoreCase("str3")) {

我必须回答你的问题。第一个问题是为什么我们运行这个函数时会出现ConcurrentModificationException

public static void testList() {
    List<String> list = new ArrayList<String>();
    list.add("str3");

    for (String st : list) {
        if (st.equalsIgnoreCase("str3")) {
            list.remove("str3");
        }
    }
    System.out.println(list);
}
publicstaticvoidtestlist(){
列表=新的ArrayList();
列表。添加(“str3”);
for(字符串st:list){
if(st.equalsIgnoreCase(“str3”)){
列表。删除(“str3”);
}
}
系统输出打印项次(列表);
}
我喜欢这个东西,因为增强了使用迭代器(它检查
modificationscont
),但我要求确定。这就是例外的原因

第二个问题是我是否使用了
Collections.synchronizedList(newlinkedlist())
我可以使用2个或更多的增强for循环吗?例如,我必须执行线程,有时第一个线程从集合中删除元素,有时第二个线程在集合中添加元素。我认为即使在我们使用迭代器时也应该进行线程保存(我认为迭代器的功能得到了增强)。

提前谢谢。

第一个问题,是的。如果列表正在枚举,则修改列表时,这是常见的异常


关于第二个问题,是的。但是您需要为each for循环使用
synchronized

如果您在迭代列表时从列表中删除元素,您将得到一个
ConcurrentModificationException
。为了避免这种情况,您应该使用显式迭代器而不是增强的
for
循环,并在找到必须删除的元素时,在迭代器上而不是在列表上调用
remove()

for (Iterator<String> i = list.iterator(); i.hasNext(); ) {
    String st = i.next();
    if (st.equalsIgnoreCase("str3")) {
        // Remove the element that the iterator is currently pointing to
        i.remove();
    }
}
for(迭代器i=list.Iterator();i.hasNext();){
字符串st=i.next();
if(st.equalsIgnoreCase(“str3”)){
//删除迭代器当前指向的元素
i、 删除();
}
}
仅使用集合包装列表。synchronizedList(…)
不能使多个线程同时在列表上迭代,其中一个线程正在从列表中删除元素。执行此操作时,您仍然会得到一个
ConcurrentModificationException
。使用集合包装列表。synchronizedList(…)将使列表上的各个方法同步,但在多个方法上没有同步


您必须确保,如果一个线程正在从列表中删除元素,则通过正确同步您自己的迭代和删除元素的方法,没有其他线程在列表中迭代。

迭代器在SynchronizedCollection中不同步。我已附上同步收集代码

static class SynchronizedCollection<E> implements Collection<E>, Serializable {
        private static final long serialVersionUID = 3053995032091335093L;

        final Collection<E> c;  // Backing Collection
        final Object mutex;     // Object on which to synchronize

        SynchronizedCollection(Collection<E> c) {
            this.c = Objects.requireNonNull(c);
            mutex = this;
        }

        SynchronizedCollection(Collection<E> c, Object mutex) {
            this.c = Objects.requireNonNull(c);
            this.mutex = Objects.requireNonNull(mutex);
        }

        public int size() {
            synchronized (mutex) {return c.size();}
        }
        public boolean isEmpty() {
            synchronized (mutex) {return c.isEmpty();}
        }
        public boolean contains(Object o) {
            synchronized (mutex) {return c.contains(o);}
        }
        public Object[] toArray() {
            synchronized (mutex) {return c.toArray();}
        }
        public <T> T[] toArray(T[] a) {
            synchronized (mutex) {return c.toArray(a);}
        }

        public Iterator<E> iterator() {
            return c.iterator(); // Must be manually synched by user!
        }

        public boolean add(E e) {
            synchronized (mutex) {return c.add(e);}
        }
        public boolean remove(Object o) {
            synchronized (mutex) {return c.remove(o);}
        }

        public boolean containsAll(Collection<?> coll) {
            synchronized (mutex) {return c.containsAll(coll);}
        }
        public boolean addAll(Collection<? extends E> coll) {
            synchronized (mutex) {return c.addAll(coll);}
        }
        public boolean removeAll(Collection<?> coll) {
            synchronized (mutex) {return c.removeAll(coll);}
        }
        public boolean retainAll(Collection<?> coll) {
            synchronized (mutex) {return c.retainAll(coll);}
        }
        public void clear() {
            synchronized (mutex) {c.clear();}
        }
        public String toString() {
            synchronized (mutex) {return c.toString();}
        }
        // Override default methods in Collection
        @Override
        public void forEach(Consumer<? super E> consumer) {
            synchronized (mutex) {c.forEach(consumer);}
        }
        @Override
        public boolean removeIf(Predicate<? super E> filter) {
            synchronized (mutex) {return c.removeIf(filter);}
        }
        @Override
        public Spliterator<E> spliterator() {
            return c.spliterator(); // Must be manually synched by user!
        }
        @Override
        public Stream<E> stream() {
            return c.stream(); // Must be manually synched by user!
        }
        @Override
        public Stream<E> parallelStream() {
            return c.parallelStream(); // Must be manually synched by user!
        }
        private void writeObject(ObjectOutputStream s) throws IOException {
            synchronized (mutex) {s.defaultWriteObject();}
        }
    }
静态类SynchronizedCollection实现可序列化的集合{
私有静态最终长serialVersionUID=3053995032091335093L;
最终集合c;//支持集合
最终对象互斥体;//要同步的对象
SynchronizedCollection(集合c){
this.c=Objects.requirennull(c);
互斥=这个;
}
SynchronizedCollection(集合c,对象互斥){
this.c=Objects.requirennull(c);
this.mutex=Objects.requirennull(互斥);
}
公共整数大小(){
已同步(互斥){返回c.size();}
}
公共布尔值为空(){
已同步(互斥){return c.isEmpty();}
}
公共布尔包含(对象o){
已同步(互斥){返回c.contains(o);}
}
公共对象[]toArray(){
已同步(互斥){返回c.toArray();}
}
公共T[]toArray(T[]a){
已同步(互斥){返回c.toArray(a);}
}
公共迭代器迭代器(){
返回c.iterator();//必须由用户手动同步!
}
公共布尔加法(E){
已同步(互斥){返回c.add(e);}
}
公共布尔删除(对象o){
已同步(互斥){返回c.remove(o);}
}
公共布尔containsAll(集合coll){
已同步(互斥){返回c.containsAll(coll);}
}
公共布尔addAll(集合coll){
已同步(互斥){返回c.removeAll(coll);}
}
公共布尔值保留(集合集合集合){
已同步(互斥){返回c.retainAll(coll);}
}
公共空间清除(){
已同步(互斥){c.clear();}
}
公共字符串toString(){
已同步(互斥){返回c.toString();}
}
//覆盖集合中的默认方法
@凌驾

public void forEach(ConsumerTanks,您的答案。因此,如果我有两个线程,并且每个线程中都有一个迭代器(并且其中至少一个线程更改了集合),我必须同步迭代(因为如果一个线程做了更改,另一个迭代器将检查modCount和Boom)?还有一个问题-如何实现Enhanced for,它会引发异常,但普通迭代器不会。提前感谢。是的,如果至少有一个线程正在更改集合,则需要在整个循环中同步。第二个问题:技巧是通过调用
remove()来删除
在迭代器上,而不是在列表本身上-这样迭代器知道集合已更改。通过增强的
for
-循环,您无法访问迭代器,因此无法在迭代器上调用
remove()
。感谢您的回答。这与
Collections.synchronizedList的内容大致相同(...)
可以,也不会在方法调用之间保护您免受
ConcurrentModificationException
的影响。@Jesper这不多也不少。这是synchronizedList code Only为您解答!Jesper对您有帮助吗?如果我在某个地方迭代集合,使用同步集合的原因是什么?我的意思是我必须nchronized了这个迭代b