2013-12-17 60 views
1

我已經看到:How can I pass a parameter to a Java Thread?參數傳遞到Java線程

但我不知道究竟是如何使用的。所以我做了簡單的samle代碼來節省您的寶貴時間:

class ThreadParam implements Runnable { 
static int c; 

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

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

} 

public class ThreadParamTest { 
public static void main(String args[]){ 
    Runnable r = new ThreadParam(1000,2000); 
    new Thread(r).start(); 
} 
} 

爲什麼這個結果是0?我認爲應該是3000.也許變量「int c」不是調度到run()方法。我該如何解決這個問題?

+0

你在方法ThreadParam – Vorsprung

回答

6

我覺得「靜INT C」的選擇是不正確的,這意味着所有實例ThreadParam將「共享」(並且很差),爲c的共同值。這是留,如果你有2個獨立的ThreadParams同時去,其中一人可能是本作C.「錯誤」的價值考慮...

class BadThreadParam implements Runnable { 
    static int c; 

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

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

class ImmutableThreadParam implements Runnable { 
    private final int c; 

    public ImmutableThreadParam(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, 2); 
     shouldBe3.run(); // Expect 3 but is 5. WTF? 
     shouldBe5.run(); // Expect 5. 

     ImmutableThreadParam expect3 = new ImmutableThreadParam(1, 2); 
     ImmutableThreadParam expect5 = new ImmutableThreadParam(3, 2); 
     expect3.run(); // Expect 3. 
     expect5.run(); // Expect 5. 
    } 
} 

如果使「C」本地實例,你克服了「2個獨立的ThreadParams影響相同的價值」的問題。如果您最終創建了「private int c」,那麼您就避免了同步的需要。如果您需要變異「C」向下運行(或從外),你現在進入同步的世界......

class ThreadSafeMutableThreadParam implements Runnable { 
    private int c; 

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

    public synchronized void setC(int c) { 
     this.c = c; 
    } 

    public synchronized int getC() { 
     return c; 
    } 

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

除此之外,tuxdna的是正確的描述你怎麼「通params to Runnable「。 Runnable是無關緊要的;你將params傳遞給一個類(但是你實現了這個)。如果您需要在運行()中使用它們,則需要了解同步。

4

結果爲0,因爲在構造函數中實際上並沒有爲static int c賦值新值,而是將其賦值給局部變量c

在構造函數中將int c更改爲c

+1

+1本地聲明瞭c而且,海報不希望'c'字段是靜態的。這意味着'ThreadParam'的所有​​實例共享相同的字段。 – Gray

+0

我可以再問你一個問題嗎?在我的示例代碼中,在run()方法中,如何打印變量「a」?我想表明這一點。 – Juntae

+1

您需要將'a'作爲另一個字段(非靜態)存儲在'ThreadParam'類@user3100921中。然後你可以打印它。 – Gray

3

您的'c'變量定義了兩次:一次在類級別(使用靜態修飾符),一次在ThreadParam構造函數中。刪除類字段上的「靜態」,並刪除構造函數中的「int」。

4

c不應該是靜態的,應該在您的構造函數中進行賦值。 在您的示例中,您已將其分配給變量c,而不是該字段。

以下是更正代碼:

class ThreadParam implements Runnable { 
private int c; 

public ThreadParam(int a, int b){ 
    this.c = a+b; 
} 

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

} 
2

Runnable的僅僅是需要你定義一個run()方法,沒有多也不少的接口。所以,基本上,你可以自由地以任何你想要的方式聲明你的類構造器(你傳遞了兩個整數ab),以便能夠從run()方法訪問它們。

此外,您正在構造函數中定義一個局部變量在構造函數完成後被銷燬。這使static int c值仍爲0

這裏是固定的版本:

class ThreadParam implements Runnable { 
    private int c; 

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

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

} 

public class ThreadParamTest { 

    public static void main(String args[]) { 
     Runnable r = new ThreadParam(1000, 20000); 
     new Thread(r).start(); 
    } 
} 

,輸出爲21000(而不是3000

+1

這段代碼在技術上是正確的,但是「static int c」可能不是這裏的最佳選擇,因爲它意味着所有的ThreadParam都會共享這個共同的值。而且,每次新的ThreadParam被更新時,他們都會看到它發生了變化。我希望這個聲明至少是「private final int c」,以使它成爲本地和不可變的實例,因此是線程安全的。如果你需要在外面發佈「c」創建一個「public int getC(){return c;}並且你很好,如果想在運行或外部改變」c「,現在你需要保護它同步 –

+1

@BobKuhar同意,它('c')應該是私有的,但是這個代碼是供原作者參考的,修正了它。 – tuxdna