2011-03-10 99 views
3

美好的一天! 我得到了有關在java中同步線程的問題。我正在開發創建計時器的程序,並允許重置它,刪除和停止。只是爲了學習如何使用線程。在java中同步線程

問題是代碼只能同步一段時間......我無法理解我的錯誤。也許我的方式是錯誤的,所以我想知道如何解決這個問題。

我有下面的代碼:

public class StopWatch 
{ 
    //Create and start our timer 
    public synchronized void startClock(final int id) 
    {         
      //Creating new thread. 
      thisThread = new Thread() 
      { 
       @Override 
       public void run() 
       { 
        try 
        {            
         while(true) 
         { 
          System.out.printf("Thread [%d] = %d\n", id, timerTime); 
          timerTime += DELAY;          //Count 100 ms 
          Thread.sleep(DELAY);          
         } 
        } 
        catch(InterruptedException ex) 
        { 
         ex.printStackTrace(); 
        } 
       } 
      }; 

      thisThread.start();   
    } 

… 
    //Starting value of timer 
    private long timerTime = 0; 
    //Number of ms to add and sleep          
    private static final int DELAY = 100;         

    private Thread thisThread; 
} 

我調用這個類,如:「?只給你同步一段時間」

StopWatch s = new StopWatch(1); 
      s.startClock(); 
StopWatch s2 = new StopWatch(2); 
      s2.startClock(); 
+3

我想你不理解什麼「同步」意味着與線程編程有關。它跟時間沒有任何關係。 – 2011-03-10 19:00:36

+0

@布萊恩羅奇 是的,你是對的。我在這裏學習很多東西。 – ExiRe 2011-03-10 19:17:31

回答

7

我想你可能誤解了「同步」。

這並不意味着線程在完全同步的時間內運行 - 而是一次只允許一個線程執行同步的代碼塊。在你的情況「同步」沒有什麼區別,因爲你是從同一個線程調用startClock方法... ...

一般來說,Java(甚至是大多數高級語言)不可能保證兩個線程因爲它們總是容易被OS調度程序或JVM垃圾收集暫停等延遲,所以即使您有多個內核,也能在完全相同的時鐘時間執行操作。

此外,Thread.sleep(...)不可靠作爲計時機制,因爲它睡覺的時間只是近似的。你受線程調度程序的支配。

建議解決方案:

使用System.currentTimeMillis()如果你想有一個線程獨立定時mechansim。

+0

這是否意味着如果我會在同一時間啓動2個定時器(使用線程),然後我會在同一時間停止它們,我不能保證相同的值?我理解對嗎? – ExiRe 2011-03-10 19:08:13

+0

正確。線程睡眠不是一個準確的時間機制。如果您想要一致的計時器值,請使用System.currentTimeMillis()或類似的。 – mikera 2011-03-10 19:10:31

+0

我從他所描述的內容中搜集了什麼,並且synchronized關鍵字沒有提供。即使因爲他使用同步關鍵字,其他所有內容都是平等的,他們也永遠不會在同一時間運行,並始終關閉。 – 2011-03-10 19:18:31

2

你這是什麼意思是你在這裏同步的唯一的東西是startClock方法,它只是意味着兩個線程不會同時在該方法內(並且看起來你不會這麼做)。例如,如果您想同步對timerTime的訪問,則需要在遞增的timerTime周圍的線程運行方法內部放置一個同步塊(或者您可以使用AtomicLong)。

0

您應該重新閱讀「同步」關鍵字的文檔。我很確定在這種情況下,它所要做的就是讓StartClock()的兩個調用同時執行,這不會發生在給定代碼的情況下,因爲它們是從一個線程中一個接一個地調用的。一旦計時器線程開始,如果這是您的目標,則沒有任何事情可以保持它們的同步。

0

您的第一個問題是,這是一個僅基於時間的解決方案。這很糟糕,因爲程序無法控制執行所花費的時間。某些操作比其他操作需要更多時間,並且流程中的每個線程都不會同時執行。一般情況下,除非可以保證其他部分相同,否則不會同步任何內容。 。 。

閱讀http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Semaphore.html,你也可以做

的Thread.join();在繼續執行之前讓主循環等待子線程的執行完成。

0

我想你誤解了同步的意思。同步是爲了確保多個線程對某個代碼塊的訪問權限有限,這樣您就不會在兩個線程之間發生衝突。

我想你可能更感興趣的是CyclicBarrier或CountDownLatch。兩者都可以用於「同步」(在這種情況下,重載使用)多線程,以便他們嘗試同時開始做事。

但是,請注意,不可能讓多個線程在正好同時處理事情。你只能試着鼓勵大約在同一時間去做。其餘部分受系統內核操作系統調度影響。如果你有一個核心,他們將永遠不會同時運行。