我尝试使用两个单独的线程来实现wait / notify机制来修改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!! :)
答案 0 :(得分:1)
不要重新发明轮子,只需使用CopyOnWriteArrayList
。它具有开箱即用的并发性。
答案 1 :(得分:1)
唯一的问题是removeFromList只运行一次(因为你推荐了for循环)。这就是为什么日志中没有第二个删除并且addToArrayList开始等待的原因(等待有人从列表中删除该项目)。
我在删除评论后尝试了您的代码并且工作正常!
答案 2 :(得分:0)
您的notifyAll位于synchronized块内。所以另一个线程可能会在他行动之前被唤醒。所以它可能会受阻。
我不确定我是否了解你的目标,但这种结构可能更好:
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();
}
但这非常复杂。你有更普遍的目标吗?也许只有一个线程的任务队列可以更好地适合你:它会更快,更轻,更简单,并且可以并行化(根本不是)。