我有一个显示秒表的线程,比如减少时间。这个线程计数1分钟。在这一分钟内,用户必须回答一个问题。如果用户在完成一分钟之前回答问题,则向他显示下一个问题并且线程被重置为计数1分钟。
我面临的问题是,当我调用reStartTimeKeeper()时,计时器重新启动但开始计数更快。随后的每次调用都会进一步提高计数器的速度。我的意思是,在第一次调用reStartTimeKeeper()之后,我的timmer在30秒(大约)内计算60秒,在第二次调用reStartTimeKeeper()之后,我的timmer在15秒(大约)内计算60秒。等等。
原因是当我在reStartTimeKeeper()中设置Question_Time = -1时,线程的第一个实例被暂停。它不断执行while循环,就好像它正在等待while()中的条件变为true。
当我尝试启动线程的第二个实例时,我设置Question_Time = 60。这将启动线程的新实例。这样做也可以激活休眠的第一个实例,它等待条件变为真。
我只想在任何时刻获得我的线程的一个实例。我把它变成了一个静态变量。这样做也没有效果。
int Question_Time=-1;
static Thread timeKeeper;
Handler mHandler = new Handler();
void Start_TimeKeeper()
{
Question_Time=60;
timeKeeper = new Thread(new Runnable() {
@Override
public void run() {
while (Question_Time!=-1)
{
mHandler.post(new Runnable()
{
@Override
public void run()
{
Question_Time--;
UpdateUI();
}
});
try
{
Thread.sleep((1000));
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
});
timeKeeper.start();
}
void reStartTimeKeeper()
{
Question_Time=0;
while(Question_Time==-1);
Start_TimeKeeper();
}
如果有人可以同步这个流程,那就太好了! 如果你发现任何愚蠢的事情或一些改进的建议,那将是非常受欢迎的。 谢谢!
当我尝试启动线程的第二个实例时,我设置Question_Time = 60。这将启动线程的新实例。并且这样做也激活休眠的第一个实例,它等待条件变为真。我想完全杀死线程的第一个实例,当它被杀死时,我想安全地重新启动新的实例。
答案 0 :(得分:1)
当你致电Start_TimeKeeper();
时,它会启动另一个线程而不会停止第一个线程。所以你的两个线程减少了时间。这就是它计算速度更快的原因。
不是每次都创建一个新线程,而是只检查旧线程是否已完成,如果是,请启动一个新线程,否则只需重置Question_Timeint
。
class TimeKeeper extends Thread {
private volatile boolean run = false;
@Override
public void run() {
run=true;//run while run=true
while (run) {
if (Question_Time >= 0) {
mHandler.post(new Runnable() {
@Override
public void run() {
Question_Time--;
UpdateUI();
}
});
}
try {
Thread.sleep(Question_Time >= 0 ? 1000 : 5000);//loop with longer delays if question time is below zero
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void finish() {
run = false;
}
}
使用此TimeKeeper类。启动一次,每次都使用,重置变量重启。
答案 1 :(得分:0)
两个主要问题(除了整个方法的概念问题):
没有同步。正如安迪在评论中所说:
内存可见性。时间是非易失性原语。无法保证线程中的while
实际上看到剩余的最新时间值。
通过在你剩下的时间内使用一个原子变量可以缓解这两个问题(并且对你如何使用它进行了一些思考,只需要调用.get()
到本地var就不会起作用了。 / p>
更好的方法是不要产生这么多线程。使用一个无限循环的单个时间线程,当设置一个布尔标志时 - 递减计数器。
如果您仍想生成线程并正确杀死它们 - 这应该有所帮助:Stop, interrupt, suspend and resume a java thread