2017-04-23 27 views
0

所以我想將參數傳遞給我的線程,而且我的輸出結果並不如預期。下面是我的代碼:將參數傳遞給線程方法時輸出結果不同

class BadThreadParam implements Runnable { 
    static int c; 

    public BadThreadParam(int a, int b) { 
     c = a + b; 
    } 

    public void run() { 
     System.out.println(c); 
    } 
} 

public class BadThreadParamTest { 
    public static void main(String[] args) { 
     BadThreadParam shouldBe3 = new BadThreadParam(1, 2); 
     BadThreadParam shouldBe5 = new BadThreadParam(3, 12); 
     shouldBe3.run(); // Expect 3 but is 15. WTF? 
     shouldBe5.run(); // Expect 15. 
    } 
} 

我期待最終的輸出是:

3 
15 

,但我得到:

15 
15 

所以這是線程干擾的問題?任何人都可以解釋爲什麼會發生?

回答

1

如果你改變

static int c; 

private int c; 

既然你不訪問變量c出你的類的,沒有任何理由應該是靜態的。如果你把它變成靜態的,每次你改變它,它就是最後一個值。

如果將其更改爲private,則它是一個「實例」變量,它鏈接到您使用新的BadThreadParam()創建的實例;所以輸出是賦予特定實例的值。

0

c是一個靜態變量。這意味着當一個線程改變它時,每個人都會改變它。

您可能打算將它作爲實例變量。

+0

你能更具體一點嗎?就像我如何獲得理想的輸出? – user227666

+0

我真的不知道我怎麼可以更具體。 –

0

我只是重新排序在main方法的線,這裏的區別是

public static void main(String[] args) { 
    BadThreadParam shouldBe3 = new BadThreadParam(1, 2); 
    shouldBe3.run(); 
    BadThreadParam shouldBe5 = new BadThreadParam(3, 12); 
    shouldBe5.run(); 
} 

這裏是輸出

3 
15 

有一起來看看這款張貼答案一起@JC97 & @Joe C 希望這會清除你對靜態變量的疑惑

0

你問你是否看到的問題是由線程干擾引起的。在發佈的程序中沒有線程干擾的可能性,因爲只有一個線程。在Runnable上調用run可以在當前線程中執行它。

如果你想創建一個新的線程來執行您的每一個的Runnable,那麼你應該更改代碼以

new Thread(shouldBe3).start(); 
new Thread(shouldBe15).start(); 

,然後你將有多個線程的程序。此時,不能保證一個線程將在另一個線程之前打印其輸出。

爲了證實這一點,你可以行

System.out.println(Thread.currentThread().getName()); 

添加到每個run方法的主體和主要方法。如果他們都打印相同的名稱,那麼你不會創建任何線程。

正如其他答案所說,你讓第二個構造函數調用覆蓋由第一個構造函數調用的c集的內容。 static關鍵字表示變量屬於類,不屬於任何一個實例,所有實例都訪問相同的變量。 c應該是一個實例變量(刪除static關鍵字),以便每個Runnable對象都有自己的副本。