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

时间:2014-12-27 20:54:45

标签: java multithreading arraylist

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

  • 将“第0行”添加到arraylist
  • 打印arraylist中的最后一项,即“line 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;
        }

    }


}

4 个答案:

答案 0 :(得分:6)

可能您的held变量不是volatile导致死锁。计算机上的不同核心将拥有自己的内存缓存,这些缓存不一定同时更新。要确保所有线程都可以看到保持的更改,您应该使其变得不稳定。您还可以使用AtomicBoolean,或同步访问代码块。

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

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