Java 如何使两个线程轮流修改arraylist?

Java 如何使两个线程轮流修改arraylist?,java,multithreading,arraylist,Java,Multithreading,Arraylist,下面您将看到的代码试图实现以下目标: 将“第0行”添加到arraylist中 打印arraylist中的最后一项,即“第0行” 从arraylist中删除最后一项 将“第1行”添加到arraylist中 打印arraylist中的最后一项,即“第1行” 从arraylist中删除最后一项 ……等等,没完没了 因此,我期望的结果很简单: 第0行 第1行 然而,我得到的是一个随机数量的“线I”,其中我也是随机的。 以下是一个示例输出: 第0行 第38919行 第47726行 第54271行

下面您将看到的代码试图实现以下目标:

  • 将“第0行”添加到arraylist中
  • 打印arraylist中的最后一项,即“第0行”
  • 从arraylist中删除最后一项

  • 将“第1行”添加到arraylist中

  • 打印arraylist中的最后一项,即“第1行” 从arraylist中删除最后一项
……等等,没完没了

因此,我期望的结果很简单:

第0行

第1行

然而,我得到的是一个随机数量的“线I”,其中我也是随机的。 以下是一个示例输出:

第0行

第38919行

第47726行

第54271行

然后,程序陷入似乎是死锁的状态,即使这没有意义,因为变量“hold”只能是true或false,并且这两种情况都应该允许其中一个线程工作

import java.util.*;

public class Test {

     static boolean held = true;
     static ArrayList<String> line = new ArrayList<>();


     public static void main(String[] args) {

        new Thread() {
            @Override
            public void run() {
                int i = 0;
                while(true) {
                    if(held) {
                        line.add("Line " + i);
                        i++;
                        held = false;
                    }
                }
            }


        }.start();

        while(true) {
            if(!held) {
                System.out.println( line.get(line.size() - 1) );
                line.remove(line.size() - 1);
                held = true;

            }else continue;
        }

    }


}
import java.util.*;
公开课考试{
静态布尔值=真;
静态ArrayList行=新建ArrayList();
公共静态void main(字符串[]args){
新线程(){
@凌驾
公开募捐{
int i=0;
while(true){
如果(举行){
行。添加(“行”+i);
i++;
保持=假;
}
}
}
}.start();
while(true){
如果(!保持){
System.out.println(line.get(line.size()-1));
line.remove(line.size()-1);
保持=正确;
}否则继续;
}
}
}

您可以使用两个线程同步的锁对象,然后让每个线程在列表上执行它们的操作,然后使用wait和notify交替唤醒另一个线程,该线程也会执行相同的操作。

可能是您的
hold
变量不是
volatile
导致了死锁。计算机上的不同内核将有自己的内存缓存,不一定同时更新。要确保对保持的更改对所有线程都可见,应将其设置为易失性。您还可以使用AtomicBoolean,或同步对代码块的访问。

我认为在这种情况下,最好使用同步的列表,而不是arraylist:

List line = Collections.synchronizedList(new ArrayList(...));

首先,在main中创建两个不同的线程,第一个线程(子线程)和main的线程,它们将处理main的while循环。这意味着您同时运行它们,因此您无法确定当每个线程使用它时,hold的值是多少。要解决这个问题,您必须使用信号量或互斥来访问hold进行更改


第二件事是,在while循环中,没有任何东西可以使程序脱离它们,这就是为什么它可能会导致无限循环。

我在ideone上运行了这个程序,输出与您预期的一样。所以这一定是平台相关的问题。尝试将
volatile
添加到保持变量。您可以尝试使用
信号灯
@Martijn-courtaux制作“保持”volatile,谢谢!此行为在@VGR“编译器可以对任一线程中的指令进行重新排序,但这不会影响该线程的独立执行”-现在,我的程序的行为已得到解释,谢谢!