2011-09-08 36 views
3

我想了解下面的程序。如果我打電話new ReaderThread().start()它工作正常,但如果我打電話new ReaderThread().run(),應用程序進入無限循環。有什麼不同?Java中的線程爭用

public class Contention { 

    private static boolean ready; 
    private static int number; 

    private static class ReaderThread extends Thread { 
     public void run() { 
       while (!ready){ 
       System.out.println("ready ..."+ready); 
       Thread.yield();} 
      System.out.println(number); 
      // } 
     } 
    } 


    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     // TODO Auto-generated method stub 
     new ReaderThread().run(); 
     number = 42; 
     ready = true; 

    } 

} 
+0

檢查答案在這裏:http://stackoverflow.com/questions/3027495/java-thread-run-and-start-methods – BenCole

回答

2

如果您使用new ReaderThread().start();,您實際上正在創建一個新的線程實例,該實例將在後臺運行,並且main()將繼續執行。

new ReaderThread().run();創建這個類的一個實例,並進行了一次正常的方法調用run()方法,所以main()必須等到run()已經執行完畢並返回控制返回主(),而你的情況是一個無限循環。

如果你想開始一個新的線程,然後開始使用ReaderThread().start();這是啓動一個線程的正確方法,沒有替代品。

11

當你打電話給run()你這樣做在同一個線程。它只是一個方法調用。

當你打電話start()到觸發另一個線程調用run()

這其中的原因它不是一個好主意,擴展Thread一個,而是實現您與線程包Runnable接口。這是混淆的潛在根源之一。


這裏是你

static String name = "Peter Lawrey"; 
static String state = "Washington"; 

static String getName() { 
    return name; 
} 

static String getState() { 
    return state; 
} 

static class NamedThread extends Thread { 
    @Override 
    public void run() { 
    System.out.println(getName()+" - "+getState()); 
    } 
} 

public static void main(String... args) throws InterruptedException { 
    new NamedThread().start(); 
} 

打印

Thread-0 - RUNNABLE 

你能明白爲什麼相關傳情?

+2

+1爲厚臉皮和具有啓發性的同時:) – pap

+0

我不確定彼得,你能向我解釋一下嗎? – Raj

+0

我執行上面的代碼,通過實現runnable並使用run方法它顯示正確的名稱,但通過擴展Thread類並使用start()方法,它顯示爲Thread-0-RUNNABLE.Could請你說明這裏發生了什麼。 – Raj

4

run()只是一種不會啓動新線程的方法 - 所以main()將永遠不會設置readytrue

只有start()實際上會產生一個單獨的執行線程 - 這就是你所需要的。

請注意,即使是這樣,由於內存模型問題,您的代碼也無法保證工作 - 您需要擔心您對共享數據所做的更改的可見性。

1
public class Contention { 

    private static boolean ready; 
    private static int number; 

    private static class ReaderThread extends Thread { 
     public void run() { 
       while (!ready){ 
       System.out.println("ready ..."+ready); 
       Thread.yield();} 
      System.out.println(number); 
      // } 
     } 
    } 




    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     // TODO Auto-generated method stub 
     new ReaderThread().run();//control goes to run() method 

//and it keeps running and next line of code where you set ready=true will not be executed 
     number = 42; 
     ready = true; 

    } 

} 

編輯:

,因爲線程不起來(但同時)運行,但OS決定哪一個運行,並確保每個線程獲取基於分時基礎上自己的機會(或任何算法)。所以可能在你的情況下other thread得到機會第一,它被執行之前main()線程有機會運行並設置ready = true.但如果你再次運行你的代碼,另一種情況也是可能的。其中ready = true;已設置,並且Thread將不會輸入While()循環。

+0

謝謝,假設我說我正在使用start()而不是run(),所以控制準備就緒= true;,但是在while循環中它應該總是爲false,因爲我正在檢查!ready.How控制進入while循環。 – Raj

+0

@Raju Komaturi ..請參閱我的編輯答案.. – ngesh

+0

當您使用「開始」而不是「運行」時,新線程開始並且yield讓主線程運行,然後主線程將值設置爲true,當「新線程」有機會開始運行時,它會檢查值並退出循環。 – Delta

1

當你有new ReaderThread().run();它是在同一個線程和ready = true;永遠不會到達。

但是,當你打電話new ReaderThread().start()它啓動一個新的線程和主線程也繼續,並會擊中ready = true; - 這將使線程創建的循環... ...

+0

那麼哪個線程正在while循環中執行代碼 – Raj

+2

當您使用新的ReaderThread()。start() - 它執行while循環的ReaderThread - 當您使用新的ReaderThread().start()它的主線程時。 。 –