0

我尝试实现等待/通知机制来修改ArrayList使用两个单独的线程。

第一次迭代似乎工作正常,但第二次迭代它在addToArray()方法中永远等待。我无法弄清楚为什么它在方法中永远等待?根据我的理解,当其他线程等待时,其他线程(删除项目)应该接起。

请查看并指出可能的错误(如果有)。我知道我可以用来Vector进行线程安全操作,但这不是我想要的。

package threadTest;
import java.util.*;

public class DhagaJava {

    public static void main(String...strings){
        ArrayModification am = new ArrayModification();

        Thread t1 = new Thread(new AddToArray(am));
        Thread t2 = new Thread(new RemoveFromArray(am));
        t1.start();
        t2.start();
    }
}

class ArrayModification{
    boolean added = false;
    ArrayList<Integer> al;

    ArrayModification(){
        al = new ArrayList<Integer>();
    }

    public synchronized void addToArrayList(int x) {
        if (added == true){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.al.add(x);
        System.out.println(al);
        System.out.println("Added!! :)");
        added = true;
        notifyAll();
    }

    public synchronized void removeFromList(){
        if( added== false){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(al);     
        this.al.remove(0);
        System.out.println("Removed!! :' ");
        added = false;
        notifyAll();
    }
}

class AddToArray implements Runnable{

    ArrayModification ma;

    AddToArray(ArrayModification m){
        this.ma = m;
    }

    public void run() { 
        for (int i = 0; i<10; i++)
            ma.addToArrayList(i);
    }
}

class RemoveFromArray implements Runnable{

    ArrayModification ma;

    RemoveFromArray(ArrayModification a){
        this.ma = a;
    }

    public void run(){
            ma.removeFromList();
    }
}

class RemoveFromArray implements Runnable{

      ArrayModification ma;

      RemoveFromArray(ArrayModification a){
            this.ma = a;
      }

      public void run(){
            //for(int j=11;j<20; j++)
                  ma.removeFromList();
      }
}

输出是:

[0]
Added!! :)
[0]
Removed!! :' 
[1]
Added!! :)
4

3 回答 3

1

与其重新发明轮子,不如使用CopyOnWriteArrayList. 它具有开箱即用的并发性。

于 2012-06-01T07:27:49.070 回答
1

你唯一的问题是 removeFromList 只运行一次(因为你推荐了 for 循环)。这就是日志中没有第二次删除并且 addToArrayList 开始永远等待的原因(等待有人从列表中删除该项目)。

我在删除评论后尝试了您的代码并且工作正常!

于 2013-02-17T11:13:23.490 回答
0

您的 notifyAll 在同步块内。所以其他线程可能在他行动之前就被唤醒了。所以可能会被屏蔽。

我不确定我是否理解您的目标,但这种结构可能会更好:

public void addToArrayList(int x) {
    synchonized(this.al) {
        if (added == true){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.al.add(x);
        System.out.println(al);
        System.out.println("Added!! :)");
        added = true;
    }
    notifyAll();
}

但这非常复杂。你有更普遍的目标吗?也许只有一个线程的任务队列更适合你:它会更快、更轻、更简单,并且并行化(根本不是)。

于 2012-06-01T07:19:43.150 回答