2015-06-11 49 views
0

我正在玩多線程,並在運行一小段代碼時遇到了不一致。下面的代碼應打印出123123 ...但我得到的是爲什麼線程不能一致運行?

class RunnableDemo implements Runnable { 
    private String message; 

    RunnableDemo(String m) { 
     message = m; 
    } 

    public void run() { 
     try { 
      for (int i = 0; i < message.length(); i++) { 
       System.out.print(message.charAt(i)); 
       Thread.sleep(1000); 
      } 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 

    } 

} 

public class TestThread { 
    public static void main(String args[]) throws InterruptedException { 

     new Thread(new RunnableDemo("1111111")).start(); 
     new Thread(new RunnableDemo("2222222")).start(); 
     new Thread(new RunnableDemo("3333333")).start(); 

    } 
} 

輸出:123231231132123231321

輸出:123213123123213213213

輸出:123231213213231231213

什麼我不明白的是它在第一次傳球(打印'123')時正確運行,但第二次傳球打印'231'。如果線程正在打印字符,睡眠1秒鐘,然後重複。不應該每次我運行代碼或至少按照前3個字符的模式來保持模式123123 ...一致?

+3

他們是線程,你沒有安排他們,JVM/OS是。此外,股票Java不是實時的;睡眠計數和切換的微小差異會改變結果。 –

+0

要添加到@DaveNewton的評論,您將不得不確保3個線程通過使用「同步」或鎖定一個接一個地執行 – TheLostMind

+2

我可以將此問題轉換爲:「爲什麼當我讓東西並行運行時,不是按順序發生的?「 – Gimby

回答

7

下面的代碼應打印出123123

不一定。你應該基本上從來沒有依賴線程之間沒有任何同步發生喚醒和執行任何特定的順序。

讓我們首先看字符輸出:不能保證那將是1.是的,你首先開始打印線程1,但這並不意味着這是第一個線程將會真正開始執行首先 - 或者即使是這樣,這並不意味着這是第一個線程將會達到System.out.print的呼叫。

鑑於相當長的睡眠,我預期(但最好不要依賴)的輸出端與7「塊」,其中每個「塊」由在某個置換字符「123」的序列。但是,如果你有三個線程同時「大致」地睡一秒鐘,你不應該指望他們一定會以1,2,3的順序醒來 - 即使他們做了也是如此,其中一個可能搶先在循環體內的另一個。

在一個非常,非常慢的機器,即使是預期是無效的 - 想象可以是0到20秒之間的一個隨機時間打電話charAt - 不可能的,但它是一個可行的想法實驗。此時,其中一個線程可以在其他線程設法打印任何東西之前競賽並完成其輸出。

線程被設計爲獨立的 - 如果你希望他們以協調的方式工作,你必須自己指定協調。這項工作有很多工具,但不要指望它發生神奇的事情。

+0

我喜歡思想實驗。 –

+0

謝謝。真的很好的解釋。 – Woodsy

0

您無法預測某個程序CPU一次運行的程序。在運行某個進程時,CPU將進程轉換爲work的小塊。隨着多個進程一次運行。 CPU必須按照scheduling algorithm的時間表執行。因此,簡而言之,除非以編程方式同步這些代碼片段,否則無法預測接下來的CPU。

相關問題