Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/398.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

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_Synchronized - Fatal编程技术网

Java 访问不同线程上的列表的输出是什么?

Java 访问不同线程上的列表的输出是什么?,java,multithreading,synchronized,Java,Multithreading,Synchronized,我有一个ArrayList的Strings,两个线程同时访问该列表。 以下代码段的输出将是什么?为什么 public static void main(String[] args) { final ArrayList<String> list = new ArrayList<String>(); for (int i = 0; i < 100; i++) { list.add("Number" + i); } ne

我有一个
ArrayList
String
s,两个线程同时访问该列表。 以下代码段的输出将是什么?为什么

public static void main(String[] args) {
    final ArrayList<String> list = new ArrayList<String>();

    for (int i = 0; i < 100; i++) {
        list.add("Number" + i);
    }

    new Thread() {

        public void run() {
            for (String s : list) {
                System.out.println(s);
            }
        }
    }.start();

    new Thread() {
        public void run() {
            list.remove("Number5");
        }
    }.start();

}
publicstaticvoidmain(字符串[]args){
最终ArrayList=新ArrayList();
对于(int i=0;i<100;i++){
列表。添加(“编号”+i);
}
新线程(){
公开募捐{
用于(字符串s:列表){
系统输出打印项次;
}
}
}.start();
新线程(){
公开募捐{
列表。删除(“编号5”);
}
}.start();
}

我尝试使用相同的代码使
Arraylist
使用
Collections.synchronizedList(list)
进行同步。它仍在抛出
java.util.ConcurrentModificationException

您正在
迭代(在第一个线程中)和
更新(在第二个线程中)两个不同线程中相同的
列表
对象,因此总是存在(可能性)它将抛出
java.util.ConcurrentModificationException

java迭代器本质上是快速失效的,因此,一旦他们意识到下划线结构已被更改,就会出现
ConcurrentModificationException
异常

如果您想为您的需要使用相同的列表对象,您可以考虑在代码< >运行< /COD>方法> < /P>中使用<代码>同步(列表)< /代码>进行同步。

    public void run() {
        synchronized(list) {
          for (String s : list) {
              System.out.println(s);
          }
        }
    }

    public void run() {
        synchronized(list) {
          list.remove("Number5");
        }
    }

我认为你应该使用
Vector
而不是
ArrayList
作为
ThreadSafe
的工具,并使用
Iterator
浏览列表。

你可以使用关键字锁定
列表
对象

同步关键字
其总体目的是只允许一个线程 在一段时间内进入特定的代码段,从而允许我们 例如,保护变量或数据不被 来自不同线程的同时修改

所以这应该对你有用:

public static void main(String[] args) {
    ...

    new Thread() {

        public void run() {
        synchronized(list){
            for (String s : list) {
                System.out.println(s);
            }
        }
        }
    }.start();

    new Thread() {
        public void run() {
        synchronized(list){
                    list.remove("Number5");
        }
        }
    }.start();

}

NB:这取决于您想要的逻辑。顺便问一下,您是希望在迭代时从列表中删除,还是希望从列表中删除?您希望这两个任务按顺序进行吗?

的Javadoc明确指出:

用户在对返回的列表进行迭代时,必须手动同步该列表:

List list = Collections.synchronizedList(new ArrayList());
 ...
synchronized (list) {
    Iterator i = list.iterator(); // Must be in synchronized block
    while (i.hasNext())
        foo(i.next());
}
不遵循此建议可能会导致不确定性行为

由于在该代码中,当您在
列表
上进行迭代时(在不同的线程中,但它是
列表
的同一实例),您将从该列表中删除,因此将抛出
ConcurrentModificationException

使用
Collections.synchronizedList
,以下代码将正常运行

final List<String> list = Collections.synchronizedList(new ArrayList<String>());
for (int i = 0; i < 100; i++) {
    list.add("Number" + i);
}

new Thread() {
    public void run() {
        synchronized (list) {
            for (String s : list) {
                System.out.println(s);
            }
        }
    }
}.start();

new Thread() {
    public void run() {
        synchronized (list) {
            list.remove("Number5");
        }
    }
}.start();
final List=Collections.synchronizedList(new ArrayList());
对于(int i=0;i<100;i++){
列表。添加(“编号”+i);
}
新线程(){
公开募捐{
已同步(列表){
用于(字符串s:列表){
系统输出打印项次;
}
}
}
}.start();
新线程(){
公开募捐{
已同步(列表){
列表。删除(“编号5”);
}
}
}.start();

你的意思是问,“这个函数是线程安全的吗?”我也是:我在寻找它的用途。如果需要,我想我们将不得不在两个线程之间交错任务。此外,添加和删除类似于生产者-消费者问题(打印整个列表需要锁定整个列表对象,这取决于开发人员的意图。)是的,这完全取决于开发人员的意图。但开发商并没有这样评论…-)