下面我有一个每秒更新一次'clock'标签的线程。一旦线程达到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 - 这是我的代码 -
我在这里实例化我的标签 -
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();
答案 0 :(得分:3)
Thread.sleep(1000);
将线程置于至少 1s的休眠状态,然后它回到准备运行状态,这不能保证它会立即运行,它只是“准备就绪”计划在将来的任何时间运行“。它将在运行它时由线程调度程序决定。例如,您可能希望检查系统时间以确切知道已经过了多长时间......
答案 1 :(得分:3)
尝试使用 ScheduledExecutorService.scheduleAtFixedRate ,它会以固定的时间间隔执行您的任务,无论上一个任务需要多长时间才能完成。
答案 2 :(得分:2)
如果您需要计时器,建议您使用Timer。还建议如果你想保持一个时钟,你不要自己尝试这样做,而是采样系统时钟。也许您想要的是样本currentTimeMillis()
答案 3 :(得分:1)
有两件事可能会有所帮助......首先,函数incrementTimer()调用convertValToTimerString()。正如你所提到的,这会引入一些减速。它不会太多,但随着时间的推移,这种延迟将会累积。你将留在当前的执行线程中。解决方案是使用模型 - 视图 - 控制器方案。该模型将是您的“val”字段。视图是标签。然后控制器将是每秒更新一次该字段的线程。通过将模型更新与查看它们所需的代码执行分开,更新线程可以不受干扰地运行。当然,您仍然需要根据模型的值定期更新标签上的文本。一个单独的线程可以解决这个问题。
所以我们拥有的是:
对于控制器,使用Timer确实是一个更好的选择,而不是像andersoj建议的那样使用调用Thread.sleep()的Runnable。你需要实现TimerTask。固定延迟的调度和固定速率的调度之间存在差异。对于像您这样的任务,固定费率是可取的,其中平均一致性比规律性更重要。请记住,如果您使用Timer,我建议的上述模型 - 视图 - 控制器方案有点矫枉过正。您可能能够将标签更新合并到TimerTask的run方法中。但只是因为它会发生得足够快。如果您的视图更新需要更多时间(对于快速更新和重绘图的组合可能就是这种情况),MVC模式将提供正确的关注点分离并使事情保持不变。