2013-05-22 99 views
-5

我有一個大小爲n的數組,填充數字1..n。Java程序不會停止

我需要總結這個數組使用m個線程,每次取兩個元素,總結它們並將總和插回數組。

這是我試圖做的。

同步的部分第一

public class MultiThreadedSum { 

    private ArrayBuffer ArrayBufferInst; 
    private int Sum; 
    private boolean Flag, StopFlag; 

    public MultiThreadedSum(ArrayBuffer ArrayBufferInst) { 
     this.ArrayBufferInst = ArrayBufferInst; 
     Sum = 0; 
     Flag = false; 
     StopFlag = false; 
    } 

    public synchronized void Sum2Elements() { 
     while(Flag){ 
      try {wait();} 
      catch (InterruptedException e){} 
     } 
     Flag = true; 
     if (StopFlag) { 
      notifyAll(); 
      return; 
     } 
     System.out.println("Removing and adding 2 elements."); 
     Sum = ArrayBufferInst.Sum2Elements(); 
     notifyAll(); 
    } 

    public synchronized void InsertElement() { 

     while(!Flag){ 
      try {wait();} 
      catch (InterruptedException e){} 
     } 
     Flag = false; 
     if (StopFlag) { 
      notifyAll(); 
      return; 
     } 
     System.out.println("Inserting the sum."); 
     ArrayBufferInst.InsertElement(Sum); 
     if (ArrayBufferInst.RetunrSize() == 1) { 
      StopFlag = true; 
     } 
     System.out.println(ArrayBufferInst); 
     notifyAll(); 
    } 

    public boolean ReturnStopFlag(){ 
     return StopFlag; 
    } 

    @Override 
    public String toString(){ 
     return ArrayBufferInst.toString(); 
    } 
} 

我已經分裂的m個線程2組,其中一半會做總結和半會做等待使用添加和通知。

public class Sum2ElementsThread implements Runnable{ 
    private MultiThreadedSum MultiThreadedSumInst;  
    public Sum2ElementsThread(MultiThreadedSum MultiThreadedSumInst){ 
     this.MultiThreadedSumInst = MultiThreadedSumInst; 
    } 

    @Override 
    public void run() { 
     while(!MultiThreadedSumInst.ReturnStopFlag()) 
      MultiThreadedSumInst.Sum2Elements(); 
    } 
} 

public class InsertThread implements Runnable{ 
    private MultiThreadedSum MultiThreadedSumInst;  
    public InsertThread(MultiThreadedSum MultiThreadedSumInst) { 
     this.MultiThreadedSumInst = MultiThreadedSumInst; 
    } 

    @Override 
    public void run() { 
     while(!MultiThreadedSumInst.ReturnStopFlag()) { 
      MultiThreadedSumInst.InsertElement(); 
     } 
    } 
} 

這裏是主要的部分:

ArrayBufferInst = new ArrayBuffer(n); 

System.out.println("The Array"); 
System.out.println(ArrayBufferInst); 

MultiThreadedSumInst = new MultiThreadedSum(ArrayBufferInst); 

ExecutorService Threads = Executors.newCachedThreadPool(); 

for (i = 0; i < m/2; i++) 
    Threads.execute(new Sum2ElementsThread(MultiThreadedSumInst)); 
for (; i < m; i++) 
    Threads.execute(new InsertThread(MultiThreadedSumInst)); 
Threads.shutdown(); 
while(!MultiThreadedSumInst.ReturnStopFlag()){} 
System.out.println("The sum of the array is " + MultiThreadedSumInst); 

和緩衝

public class ArrayBuffer { 
    private ArrayList<Integer> ArrayBufferInst; 
    public ArrayBuffer(int SizeOfBuffer){ 
     int i; 
     ArrayBufferInst = new ArrayList<>(SizeOfBuffer); 
     for (i = 0; i < SizeOfBuffer; i++){ 
      ArrayBufferInst.add(i, i+1); 
     } 
    } 

    public int Sum2Elements(){ 
     if (ArrayBufferInst.size() < 2){ 
      return -1; 
     } 
     return ArrayBufferInst.remove(0) + ArrayBufferInst.remove(0); 
    } 

    public void InsertElement(int Elem) { 
     ArrayBufferInst.add(Elem); 
    } 
    public int RetunrSize(){ 
     return ArrayBufferInst.size(); 
    } 
    @Override 
    public String toString() { 
     return ArrayBufferInst.toString(); 
    } 
} 

我的問題是關於主,有時程序停止的結束,有時它不」噸,我知道所有的線程正在退出運行方法,因爲我檢查了。

有時我會看到The sum of the array is消息,有時我不知道。

+5

只是太多的代碼來審查這個問題。您必須減少不必要的代碼,以便它更容易回答。 – Siddharth

+1

@Siddharth你的第二個評論完全沒有要求。標記。 –

+0

@CodeEnthusiastic同意。 – Siddharth

回答

0

這對你來說確實是一個很長的代碼。

也許我可以提出一種不同的溶劑。 您可以將數組分割爲m個部分(m - 是多個線程) - 並且每個線程將總結它自己的部分。當在每個線程中求和結束時 - 僅對所有部分結果進行求和。

或者我可能沒有正確地完成你的任務。請指定更多細節(完整任務)。

+0

我同意但是這是他們在作業中想要的,謝謝。 – user2102697

1

你的問題就在這裏:

public synchronized void Sum2Elements() { 
    while(Flag){ 
     try {wait();} 
     catch (InterruptedException e){} 
    } 
    Flag = true; 
    // rest of method omitted here 
} 

當首次Flag執行程序的這一部分是假,循環被忽略。此方法的所有後續執行都將導致死鎖,因爲這是您將Flag設置爲false的唯一地方。

即使中斷也不會起作用,因爲您的循環中沒有break,並且在中斷之後,您將永遠進入下一個週期和wait()

哦,並閱讀this - Java不是c#

+0

那麼,我已經檢查過所有線程正在完成那裏的工作,我相信他們這樣做。我相信一旦它開始,第一個線程將傳遞while,然後將flag設置爲true,同時阻塞所有其他線程,同時在InsertElement中,所有線程都已經在等待。當此線程到達notifyAll()時,它將允許其中一個線程在InsertElement中執行相同的操作。我錯了嗎?謝謝。 – user2102697