Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/317.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 为什么此代码没有';当多个线程使用迭代器同时在同一arraylist上工作时,不会抛出ConcurrentModificationException_Java_Iterator_Concurrentmodification - Fatal编程技术网

Java 为什么此代码没有';当多个线程使用迭代器同时在同一arraylist上工作时,不会抛出ConcurrentModificationException

Java 为什么此代码没有';当多个线程使用迭代器同时在同一arraylist上工作时,不会抛出ConcurrentModificationException,java,iterator,concurrentmodification,Java,Iterator,Concurrentmodification,这里有两个线程在同一个arraylist上工作,一个线程读取元素,另一个线程删除特定元素。我希望这会引发ConcurrentModificationException。但它不扔为什么 import java.util.ArrayList; import java.util.ConcurrentModificationException; import java.util.Iterator; public class IteratorStudies { public static f

这里有两个线程在同一个arraylist上工作,一个线程读取元素,另一个线程删除特定元素。我希望这会引发
ConcurrentModificationException
。但它不扔为什么

import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.Iterator;


public class IteratorStudies {

    public static final ArrayList<String> arr ;

    static{

        arr = new ArrayList<>();

        for(int i=0;i<100;i++) {
            arr.add("someCommonValue");
        }
        arr.add("someSpecialValue");
    }

    private static Integer initialValue = 4;


    public static void main(String x[]) {


     Thread t1 = new Thread(){
          @Override
          public void start(){
              Iterator<String> arrIter = arr.iterator();
              while(arrIter.hasNext()){
                  try {
                      String str = arrIter.next();
                      System.out.println("value :" + str);
                  }catch(ConcurrentModificationException e){
                      e.printStackTrace();
                  }
              }
                System.out.println("t1 complete:"+arr);

          }
      };


        Thread t2 = new Thread(){
            @Override
            public void start(){
                Iterator<String> arrIter = arr.iterator();
                while(arrIter.hasNext()){
                    String str = arrIter.next();
                    if(str.equals("someSpecialValue")){
                        arrIter.remove();
                    }
                }

                System.out.println("t2 complete:"+arr);

            }
        };
        
        
        t2.start();
        t1.start();
    }


}
import java.util.ArrayList;
导入java.util.ConcurrentModificationException;
导入java.util.Iterator;
公共类迭代器研究{
公共静态最终数组列表arr;
静止的{
arr=新的ArrayList();

对于(int i=0;i您已经覆盖了两个线程实例的
start
方法,而不是
run
,并且这些方法在主执行线程中完成,因此,不会同时执行线程,也不会在此处发生
ConcurrentModificationThreadException

<凯斯

ConcurrentModificationException与并发无关 您可能会认为,给定名称,CoModEx是关于并发性的。事实并非如此。如中所示,您不需要线程来获取它。在这里,这个简单的代码将抛出它:

void example() {
    var list = new ArrayList<String>();
    list.add("a");
    list.add("b");
    for (String elem : list) {
        if (elem.equals("a")) list.remove(elem);
    }
}
void示例(){
var list=new ArrayList();
列表。添加(“a”);
列表。添加(“b”);
for(字符串元素:列表){
如果(elem.equals(“a”))列表删除(elem);
}
}
这是因为EcoModex是由迭代器抛出的,这意味着发生了这种情况:

  • 有人做了一个迭代器
  • 有人以某种方式更改了列表(而不是通过迭代器的.remove()方法)
  • 有人在#1中生成的迭代器上运行任何相关方法
  • 因此,在上面的例子中,foreach循环隐式地生成一个迭代器(#1),然后调用
    list.remove
    方法(#2),然后再次点击foreach循环,我们调用该迭代器上的相关方法(
    .hasNext()
    ),瞧,出现了CoModEx

    事实上,多线程的可能性较小:毕竟,您应该假设如果您与来自多个线程的某个对象交互,该对象已损坏,因为该行为是未指定的,因此,您有一个bug,更糟糕的是,很难对其进行测试。如果您从另一个线程修改纯jane arraylist在迭代过程中,不能保证您有一个CoModEx。您可能会得到它。您可能不会。计算机可能会离开办公桌,在百老汇碰碰运气。“未指定的行为”是一个很好的表达方式:“不要,说真的。这会一直伤害到你,因为你无法测试它;这会在你开发它的整个过程中都很好地工作,而且当你向大假发客户提供重要的演示时,它会以令人尴尬的方式在你身上失败。”

    从多个线程与一个对象交互的方法非常仔细:检查特定对象的文档,明确说明发生了什么(即使用
    java.util.concurrent
    包中的内容,该包专门设计为“从多个线程与之交互”用例),如果做不到这一点,请使用锁定。这些都是棘手的事情,因此在java中执行多线程的通常方法是首先不使用共享状态。尽可能多地隔离,反转控制,并使用具有内置事务本质的消息传递策略,如消息队列(rabbitmq和friends)和数据库(有交易的)

    如何使用线程 您可以重写
    run()
    方法,然后通过调用
    start
    方法来启动线程。或者更好的方法是,不要重写run,在创建线程实例时传递一个可运行的实例

    这就是你使用线程的方式。你没有-你覆盖了start,这意味着启动这些线程根本不会生成一个新线程,它只是在你的线程中运行负载。这解释了你的具体情况,但你正在尝试做什么(通过弄乱另一个线程的列表来见证CoModEx)也不会给你一个CoModEx——它会给你一个未指明的行为,这意味着任何事情都会发生