2011-03-03 74 views
1

下面我有一个线程每秒更新一次'时钟'标签。一旦线程达到600(10分钟),计时器停止。该线程似乎每分钟大约需要五秒钟。所以当val = 60时,实际上可能已经过了65秒。我正在使用midp,所以我不认为我可以介绍任何api来帮助完成此任务。我如何提高下课的准确度?我认为什么是减慢它的方法convertValToTimerString,有没有更好的方式转换当前计时器val分钟:秒格式不使用java格式化程序apis?提高我的计时器线程的准确性

感谢,

public class LabelTimerUpdaterThread implements Runnable{ 

    public static int val = 0; 
    private int minuteValueInt = 0; 
    private int secondValueInt = 0; 
    private int tempSecondValueInt; 
    public boolean isRunning = true; 

    public LabelTimerUpdaterThread(){ 

    } 

    public void run() { 
     while(isRunning){ 
      try { 
       Thread.sleep(1000); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
      val += 1; 


      incrementTimer(); 

      if(val == 600){ 
       break; 
      } 
     } 
    } 

    private void incrementTimer(){ 
     Screen.timerLabel.setText(convertValToTimerString(val)); 
    } 

    private String convertValToTimerString(int val){ 

     String minuteValString = ""; 
     String secondValString = ""; 

     if(val < 10){ 
      minuteValString = "00"; 
      secondValString = "0"+String.valueOf(val); 
      return minuteValString+":"+secondValString; 
     } 

     if(val < 60){ 
      minuteValString = "00"; 
      secondValString = String.valueOf(val); 
      return minuteValString+":"+secondValString; 
     } 

     if(val % 60 == 0){ 
      ++minuteValueInt; 
     } 

      if(minuteValueInt < 10){ 
       minuteValString = "0"+String.valueOf(minuteValueInt); 
       int secondVal = val % 60; 
       if(secondVal < 10){ 
        return minuteValString+":0"+String.valueOf(secondVal); 
       } 
       else { 
        return minuteValString+":"+String.valueOf(secondVal); 
       } 
      } 

     return "10:00"; 
    } 

    public void stopThread(){ 
     this.isRunning = false; 
    } 

好了,现在我收到一个IllegalStateException当我尝试upedate我的定时器标签 - 这里是我的代码 -

我在这里实例化我的标签 -

timerLabel = new CustomLabelField("00:00" , Field.FIELD_LEFT , Constants.SMALL_FONT , Color.BLACK, Bitmap.getBitmapResource("bg_clock_white.png")); 

UpdateValTimer timer = new UpdateValTimer(th); 
timer.startTimer(); 

该类创建计时器类并创建将更新计时器标签的类。

public class UpdateValTimer { 

    private Timer timer; 
    private int val = 0; 
    private UpdateView uv; 
    private final CustomLabelField customLabelField; 

    public UpdateValTimer(CustomLabelField field) { 
     this.customLabelField = field; 
    } 

    public void startTimer(){ 
     timer = new Timer(); 
     uv = new UpdateView(customLabelField); 
     Thread t = new Thread(uv); 
     t.start(); 

     timer.scheduleAtFixedRate(new TimerTask() { 
      public void run() { 
       ++val;  
      } 
     }, 1000, 1000); 
    } 
} 

此类更新计时器标签 - 公共类的UpdateView实现Runnable {

private int val = 0; 
    private int minuteValueInt = 0; 
    private final CustomLabelField timerLabel; 

    public UpdateView(CustomLabelField timerLabel) { 
     this.timerLabel = timerLabel; 
    } 

    public void run() { 
     while(true){ 
      this.timerLabel.setText(convertValToTimerString(this.val)); 
     } 
    } 

    private String convertValToTimerString(int val){ 

      String minuteValString = ""; 
      String secondValString = ""; 

      if(val < 10){ 
       minuteValString = "00"; 
       secondValString = "0"+String.valueOf(val); 
       return minuteValString+":"+secondValString; 
      } 

      if(val < 60){ 
       minuteValString = "00"; 
       secondValString = String.valueOf(val); 
       return minuteValString+":"+secondValString; 
      } 

      if(val % 60 == 0){ 
       ++minuteValueInt; 
      } 

       if(minuteValueInt < 10){ 
        minuteValString = "0"+String.valueOf(minuteValueInt); 
        int secondVal = val % 60; 
        if(secondVal < 10){ 
         return minuteValString+":0"+String.valueOf(secondVal); 
        } 
        else { 
         return minuteValString+":"+String.valueOf(secondVal); 
        } 
       } 

      return "10:00"; 
     } 

} 

感谢所有帮助

这段代码似乎是正常工作的一些初步测试后。

感谢大家的帮助。

任何意见,我可以做得更好,是值得欢迎的。

public class UpdateValTimer{ 

    private int minuteValueInt = 0; 
    private Timer timer; 
    private int val = 0; 
    private UpdateView uv; 
    private CustomLabelField customLabelField; 

    public UpdateValTimer(CustomLabelField field) { 
     this.customLabelField = field; 
    } 

    public void startTimer(){ 
     timer = new Timer(); 
      uv = new UpdateView(customLabelField); 
      Thread t = new Thread(uv); 
      t.start(); 

     timer.scheduleAtFixedRate(new TimerTask() { 
      public void run() {    
       ++val;  
       uv.setVal(convertValToTimerString(val)); 
      } 
     }, 1000, 1000); 


    } 

    private String convertValToTimerString(int val){ 

      String minuteValString = ""; 
      String secondValString = ""; 

      if(val < 10){ 
       minuteValString = "00"; 
       secondValString = "0"+String.valueOf(val); 
       return minuteValString+":"+secondValString; 
      } 

      if(val < 60){ 
       minuteValString = "00"; 
       secondValString = String.valueOf(val); 
       return minuteValString+":"+secondValString; 
      } 

      if(val % 60 == 0){ 
       ++minuteValueInt; 
      } 

       if(minuteValueInt < 10){ 
        minuteValString = "0"+String.valueOf(minuteValueInt); 
        int secondVal = val % 60; 
        if(secondVal < 10){ 
         return minuteValString+":0"+String.valueOf(secondVal); 
        } 
        else { 
         return minuteValString+":"+String.valueOf(secondVal); 
        } 
       } 

      return "10:00"; 
     } 
} 


public class UpdateView implements Runnable{ 

    private String timeElapsedCounter; 
    private final CustomLabelField timerLabel; 

    public UpdateView(CustomLabelField timerLabel) { 
     this.timerLabel = timerLabel; 
    } 

    public void setVal(String timeElapsedCounter){ 
     this.timeElapsedCounter = timeElapsedCounter; 
    } 

    public void run() { 

     while(true){ 
     synchronized(Application.getEventLock()){ 
      timerLabel.setText(this.timeElapsedCounter); 
     } 
     } 
    } 

} 


     timerLabel = new CustomLabelField("00:00" , Field.FIELD_LEFT , Constants.SMALL_FONT , Color.BLACK, Bitmap.getBitmapResource("bg_clock_white.png")); 

     UpdateValTimer timer = new UpdateValTimer(timerLabel); 
     timer.startTimer(); 

回答

1

有两件事可能有帮助...首先,函数incrementTimer()调用convertValToTimerString()。如你所说,这会引起一些放缓。它不会太多,但随着时间的推移,这种延迟将会积累。你停留在当前的执行线程内。解决方案是使用模型 - 视图 - 控制器方案。该模型将是你的“val”字段。视图是标签。然后控制器将成为每秒更新一次该字段的线程。通过将模型更新从查看它们所需的代码执行中分离出来,更新线程可以不受干扰地运行。当然,您仍然需要一种方法,根据您的模型的价值定期更新标签上的文字。一个单独的线程可以照顾到这一点。

因此,我们所拥有的是:

  • 模型(在你的情况下,只需一个值)
  • 控制器(非交互式线程更新模型)
  • 的视图(标签)
  • ,更新视图

对于控制器,使用定时器线程确实是一个更好的选择,而不是使用一个Runnable是c alls Thread.sleep(),就像andersoj建议的那样。你需要实现TimerTask。固定延迟的调度和固定速率的调度是有区别的。对于像您这样的任务而言,固定比率是可取的,平均一致性比常规更重要。不要介意,如果你使用Timer,我建议的上述模型 - 视图 - 控制器方案有点矫枉过正。您可能会将标签更新纳入TimerTask的运行方法。但仅仅因为它会发生得足够快。如果您的视图更新需要更多时间(可能出现快速更新与重绘图组合的情况),MVC模式将提供适当的关注点分离并保持细微的东西。

+0

我更新了我的问题,你可以看看吗?谢谢 – 2011-03-04 12:50:59

+0

这看起来像是一些体面的MVC原则的实现。有一件事我必须提及:我已经回答了,就好像更新标签只是一种让您了解如何处理线程和定时器的精度方法。然而,如果你确实需要很高的时间精度(即如果一个准确的时钟真的是你需要的),那么andersoj的评论是最好的...使用系统时钟。 – 2011-03-04 16:23:35

3
Thread.sleep(1000); 

将使线程进入睡眠状态至少 1秒之后,它变回现成的运行状态,这并不能保证它会immediatelly运行,它只是“随时可以安排在未来任何时间运行”。当线程调度器运行时,由它决定。你可能想要例如检查系统时间,以真正知道经过了多少时间...

2

如果你想要一个计时器,建议你使用Timer。还建议如果你想维护一个时钟,你不要试图自己做,而是采样系统时钟。也许你想要的是使用采样currentTimeMillis()