2017-05-03 55 views
3

我有一個簡單的練習,我正在嘗試涉及線程。 (a)創建一個名爲SumAction的類來實現Runnable。 該類包含3個實例變量 - 開始,結束和和。開始和結束由構造函數初始化。總和被設置爲0.java線程開始不工作

(b)run()方法應該有一個for循環,它應該找到從開始到結束的所有值的總和。應該有一個方法getSum()來返回sum的值。

(c)在主創建這個運行的類,其中一個需要1和10作爲參數的2個實例中,其他需要10和20

(d)通過這些實例2層螺紋構造使螺紋t1和t2。 (e)當線程完成時,調用getSum以從兩個線程中獲取總和值以查找總體總數。

我很確定我正在做這個權利,但我仍然得到0的總和值。

這裏是我的類

public class SumAction implements Runnable { 

private int start, end, sum; 

public SumAction(int start, int end) { 
    this.start = start; 
    this.end = end; 
    sum = 0; 
} 

@Override 
public void run() 
{ 

    for (int i = start+1; i < end; i++) 
    { 
     sum += i; 
    } 

} 

public int getSum() { 
    return sum; 
} 
} 

這裏是主

SumAction run1 = new SumAction(1, 10); 

    SumAction run2 = new SumAction(10, 20); 

    Thread t1= new Thread(run1); 

    Thread t2= new Thread(run2); 


    t1.start(); 

    t2.start(); 


    System.out.println("Sum 1 : " + run1.getSum()); 

    System.out.println("Sum 2 : " + run2.getSum()); 
+0

您可能在線程完成之前打印了總和。 – Berger

+0

這兩個線程都使用join方法 –

回答

8

你不等待線程完成。您的主線程可以在其他線程完成計算之前或在它們開始之前調用getSum。即使線程確實發生在println之前,也可能主線程看不到更新後的值。

調用連接上的線程等待,直到他們完成後,啓動線程後和printlns前補充一點:

t1.join(); 
t2.join(); 

這可以確保主線程等待,直到其他線程試圖打印前完成總和,並且還負責可見性問題。

在很多情況下,如果有足夠的預防措施(同步,使字段易失等等),從另一個線程寫入的字段中讀取線程是有問題的(錯誤的,實現相關的,或只是混淆和難以推理) )不被採取。但是在這段代碼中,如果您調用join,那麼主線程不需要額外的同步來查看getSum的最新值,因爲有一個適用的before-before規則。從Oracle tutorial報價:

當一個線程終止,並導致的Thread.join在另一個線程返回,則全部由終止線程執行的語句有之前發生的所有繼成功加入語句關係。代碼在線程中的效果現在對執行連接的線程可見。

連接方法拋出InterruptedException,如果線程在設置了中斷標誌後進入睡眠或等待狀態,則拋出檢查異常。對於一個簡單的示例程序,其中您並未真正中斷任何事情,您可以將其添加到主方法的throws子句中。