提高我的计时器线程的准确性 [英] Improve accuracy of my timer thread

查看:45
本文介绍了提高我的计时器线程的准确性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面有一个线程每秒更新一次时钟"标签.一旦线程达到600(10分钟),计时器就会停止.线程似乎每分钟落后大约五秒钟.因此,当val = 60时,实际上可能已经过去了65秒.我正在使用midp,所以我认为我无法引入任何api来帮助我完成此任务.我该如何提高下课时的准确性?我认为什么是减慢方法convertValToTimerString的速度,是否有更好的方法将当前计时器val转换为minutes:seconds格式,而无需使用Java Formatter API?

Below I have a thread that updates a 'clock' label once per second. Once the thread reaches 600 (10 mins) the timer stops. The thread seems to trail by approx five seconds every minute. So when val = 60, in actuality 65 seconds may have elapsed. I'm using midp so I dont think I can introduce any api's to help me with this task. How can I improve on the accuracy below class? I think whats slowing it down is the method convertValToTimerString, is there a better way of converting the current timer val to minutes:seconds format without using java formatter 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- 这是我的代码-

Ok, now I am receiving an IllegalStateException when I try to upedate my timer label - Here is my code -

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

Here i am instantiating my label -

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();

此类创建计时器类,并创建将更新计时器标签的类.

This class creates the timer class and creates the class which will update the timer label.

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 {

This class updates the timer label - public class UpdateView implements 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";
        }

}

感谢您的帮助

经过一些初步测试后,此代码似乎可以正常工作.

After some initial testing this code seems to be working correctly.

感谢大家的帮助.

欢迎对我可以做得更好的任何评论.

Any comments on what I could be doing better are welcome.

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();

推荐答案

有两件事可能会有所帮助...首先,函数crementTimer()调用convertValToTimerString().正如您所提到的,这将导致速度变慢.不会太大,但是随着时间的流逝,这种延迟将会累积.您将停留在当前的执行线程中.一种解决方案是使用模型视图控制器方案.该模型将是您的"val"字段.视图是标签.然后,控制器将成为每秒更新一次此字段的线程.通过将模型更新与查看它们所需的代码执行分开,更新线程可以不受干扰地运行.当然,您仍然需要一种方法,可以根据模型的值定期更新标签上的文本.一个单独的线程可以解决这个问题.

There are two things that might help... First of all, the function incrementTimer() calls convertValToTimerString(). As you mentioned, this will introduce some slowdown. It will not be much, but over time this delay is going to accumulate. You're staying within the current thread of execution. A solution would be to use a model-view-controller scheme. The model would be your "val" field. The view is the label. The controller would then be the thread that updates this field once every second. By separating the model updates from the code execution required for viewing them, the update thread can run undisturbed. Of course, you'll still need a way to regularly update the text on the label based on your model's value. A separate thread could take care of this.

所以我们拥有的是:

  • 模型(在您的情况下,仅是一个值)
  • 控制器(用于更新模型的非交互式线程)
  • 视图(标签)
  • 更新视图的线程

对于控制器,使用计时器确实是一个更好的选择,而不是使用像Andersoj建议的那样调用Thread.sleep()的Runnable.您将需要实现TimerTask.以固定延迟进行调度与以固定速率进行调度之间存在差异.对于像您这样的任务,固定速率是可取的,因为平均一致性比规则性更为重要.请注意,如果您使用计时器,则我建议的上述模型-视图-控制器方案有些过大.您可能可以将标签更新合并到TimerTask的run方法中.但这仅仅是因为它会足够快地发生.如果您的视图更新需要更多的时间(快速更新和繁重的图形结合使用可能就是这种情况),那么MVC模式将提供适当的关注点分离,并使事情变得井井有条.

For the controller, using a Timer would indeed be a better choice rather than using a Runnable that calls Thread.sleep(), like andersoj suggested. You'll need to implement TimerTask. There is a difference between scheduling at fixed delay and scheduling at fixed rate. A fixed rate is preferrable for a task such as yours, where average consistency is more important than regularity. Do mind that if you use a Timer, the above model-view-controller scheme I suggested is a bit overkill. You'll probably be capable of incorporating the label update into the TimerTask's run method. But only because it will occur fast enough. If your view update requires more time (as might be the case for a combination of fast updates with heavy drawing) the MVC pattern will provide the proper separation of concerns and keep things spiffy.

这篇关于提高我的计时器线程的准确性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆