2011-04-20 100 views
0

嗨全部
我在java中遇到了多線程問題。這是我的場景。我有一個班,名字是LocalTime。這個類應該捕獲系統的當前時間,並通過名爲getCurrentTime的方法將此值返回給Form。這是該類
Java中的多線程

public class LocalTime implements Runnable { 

private String currentTime=null; 
Thread t; 
private long time; 
private long h; 
private long m; 
private long s; 
public LocalTime() { 
    t=new Thread(this,"current Time"); 
    t.start(); 

} 

public synchronized void run() { 

    try { 
     for(;;){ 
     Thread.sleep(1000); 
        time = System.currentTimeMillis()/1000; 
        h = (time/3600) % 24; 
        m = (time/60) % 60; 
        s = time % 60; 
        this.currentTime=h+":"+m+":"+s; 
     } 
    } catch (InterruptedException ex) { 
     Logger.getLogger(LocalTime.class.getName()).log(Level.SEVERE, null, ex); 
    } 

} 
public String getCurrentTime(){ 
    return this.currentTime; 
} 

} 

的代碼,這是主要形式的代碼:

public MainForm1() { 
    initComponents(); 
    LocalTime l=new LocalTime(); 
    this.jLabel1.setText(l.getCurrentTime());//show the current time 
    //The rest of code 
} 


我現在的主要問題是jLabel1的文本,顯示當前系統時間不不更新每1秒。如果我在行jLabel1.setText(l.getCurrentTime())之前插入((;;),則其餘代碼將不可再次使用。我應該怎樣糾正這個錯誤?請用這些假設向我提出解決方案。我知道我可以在MainForm1中運行線程,但我想要解決這個問題。

+0

可能的重複http://stackoverflow.com/questions/5183318/improve-accuracy-of-my-timer-thread – 2011-04-20 13:46:03

回答

3

問題是你只讀了一次。您應該啓動一個查詢LocalTime的工作線程,或者將偵聽程序添加到LocalTime,該偵聽程序會通知時間更改並觸發標籤更新。

附註:您可能想要將new Date()SimpleDateFormat結合使用以獲得格式良好的表示形式。

+2

只需注意,你不應該從工作線程調用'setText'。因此,因爲您需要將更新重新排列在事件線程上,所以使用Rom1所示的Swing定時器要容易得多。 – 2011-04-20 13:53:07

2

請爲此類任務請使用Timer ...爲什麼要去所有額外的複雜性? 嘗試是這樣的:

int delay = 1000; //milliseconds 
    ActionListener taskPerformer = new ActionListener() { 
    final LocalTime locTime = new LocalTime(); 
    public void actionPerformed(ActionEvent evt) { 
     jLabel1.setText(locTime.getCurrentTime()); 
    } 
    }; 
    new Timer(delay, taskPerformer).start(); 
+1

我更新了更新的Javadoc的鏈接,1.4年已過時。你認爲你可以擴展如何在這裏使用Swing計時器,因爲OP可能是Swing的新手? – 2011-04-20 13:56:22

0

創建TimerTask並調用的setText在計時器的run方法。然後schedule任務每秒執行一次。

+1

'setText'需要從EDT中調用。擺動計時器是一個更好的選擇。 – 2011-04-20 13:52:10

+0

@Mark Peters - 確實如此。 OP需要在事件隊列上分派更新。這在Sun(現在的Oracle)站點中有非常清楚的解釋:http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html – 2011-04-20 14:00:31

+0

是的,這是更好的解決方案。我從來沒有在擺動工作,所以不知道擺動計時器。感謝您的評論。我只是看着thread.sleep()在循環中使用的方式,所以試圖糾正方法。 – kunal 2011-04-20 14:17:30

2

除非您不包括關鍵代碼段,否則無法將標籤更新多次。

看到,您的自定義線程正在踢每秒,更新它自己的this.currentTime字段。

但你的標籤(至少與要顯示的代碼微薄量),它只被更新一次(通過this.jLabel1.setText(l.getCurrentTime()))與任何l它有是時候場在那一刻

只是因爲本地時間線程運行,這並不意味着它會神奇地出去和更新標籤。如果你自己不編碼,爲什麼它會奇蹟般地做到這一點?想想看。

您需要做的是讓線程在其運行方法中更新標籤本身。此外,這應該在Swing線程規則(以及事件隊列)內完成。如何重構該代碼,以便獲得乾淨的代碼,這是另一個線程的主題。

// java pseudocode 

public void run() { 

    Runnable labelUpdater = new Runnable() 
    { 
     public void run() 
     { 
     someForm.jLabel1.setText(yourUpdatedTimeFormattedAsStringOrWhatever); 
     } 
    } 
    try { 
     for(;;){ 
      Thread.sleep(1000); 
      // will cause label update to occur in the awt event queue 
      SwingUtils.invokeLater(labelUpdater); 
     } 
    } catch (InterruptedException ex) { 
     Logger.getLogger(LocalTime.class.getName()).log(Level.SEVERE, null, ex); 
    } 

} 

一些注意事項:

  1. 你並不需要在你的run()方法的這一特定實例的​​關鍵字。
  2. 使用java.util.Calendar和java.util.Format獲取當前時間的字符串表示形式。你在那裏做什麼與所有的字符串連接和分割System.currentTimeMillis()的輸出是很糟糕的。你有沒有看過Java API來看看你已經有了什麼?????????

東西給你看:在Swing

併發 http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html#event_dispatching

併發(Java教程) http://download.oracle.com/javase/tutorial/essential/concurrency/

0

只有一兩件事,u的misssing是更新每秒鐘後貼上標籤。正在使用系統日期計算時間的線程正在工作正常。你可以做的是在每秒鐘後發起一個事件,並改變事件監聽器中的文本字段的值。