2012-05-23 51 views
0

我試着實現等待/通知機制,以修改ArrayList使用兩個單獨的線程。Java線程:等待通知機制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!! :) 

回答

1

你唯一的問題是removeFromList只運行一次(因爲你讚揚了for循環)。這就是爲什麼在日誌中沒有第二次刪除並且addToArrayList開始等待永久(等待某人從列表中刪除該項目)的原因。

我刪除了評論和嘗試你的代碼後,工作正常!

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(); 
} 

但是,這是非常複雜的。你有更一般的目標嗎?也許只有一個線程的任務隊列可以更好地適應你:它會更快,更輕,更簡單,並且是並行化的(根本不是)。

+1

你應該總是呼叫等待循環。 – assylias