我想在我的java(Android)程序中每2秒钟后连续生成一个随机数至少10分钟。但我只是想在一个方法中暂停/延迟执行代码而不是整个程序。
我尝试使用像这样的线程 -
boolean stop = false;
int random_number = 0;
while(true){
if(stop){ //if stop becomes true, then
return; //terminate the method
}
random_number = Math.random(); //generate random number
//which is used bu some other
//part of code
try {
Thread.sleep(2000); //delay the code for 2 secs
} catch(InterruptedException ex) { //and handle the exceptions
Thread.currentThread().interrupt();
}
}
然而,这并不起作用,Thread.sleep
停止整个程序执行而不是停止执行代码内部方法,我的整个屏幕变为空白。
我也尝试过使用Handler
,但它不起作用,因为它不会停止在我的方法中执行代码而只是堆叠。
这将证明它的工作更好 -
while(true){
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
System.out.println("After 2 secs"); //this gets printed
//later
}
}, 2000);
System.out.println("Before 2 secs"); //this gets printed first
}
因此,代码堆叠使其等同于使用while循环并使其非常慢。
此外,由于我正在为Android开发应用,我在Java SE 6上运行,因此我无法使用scheduleAtFixedRate
。还有其他方法可以实现这个目标吗?
非常感谢!
答案 0 :(得分:6)
private Timer timer;
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
//Generate number
}
}, 2000, 2000);
//Documentation (From SDK)
/**
* Schedule a task for repeated fixed-rate execution after a specific delay
* has passed.
*
* @param task
* the task to schedule.
* @param delay
* amount of time in milliseconds before first execution.
* @param period
* amount of time in milliseconds between subsequent executions.
public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
if (delay < 0 || period <= 0) {
throw new IllegalArgumentException();
}
scheduleImpl(task, delay, period, true);
}
当你想要阻止它
timer.cancel()
答案 1 :(得分:5)
选项1:使用线程,您可以在主(UI)线程上运行您的作业:
new Thread(new Runnable() {
// some code here ...
// This might be in a loop.
try {
Thread.sleep(2000);
} catch(InterruptedException ex) {
// Handle ...
}
}
}).start();
然后,如果这个新线程你想要修改UI(即显示/隐藏按钮,在屏幕上显示某些东西等),记得通过UI线程传递它,因为只有这个可以修改UI 。您可以考虑使用Activity.runOnUiThread()。
选项2 :另一种更为Android风格的方法是使用AsyncTask。它包含三个回调,可用于在UI线程上进行工作。这样的代码的草图可能如下所示:
private class MyTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... param) {
// This method is running off the UI thread.
// Safe to stop execution here.
return null;
}
protected void onProgressUpdate(Void... progress) {
// This methid is running on the UI thread.
// Do not stop thread here, but safe to modify the UI.
}
protected void onPostExecute(Long result) {
// Also on UI thread, executed once doInBackground()
// finishes.
}
}
选项3:然后还有一个Timer,正如@Stultuske所建议的那样。它不如AsyncTask
灵活,但为你处理间隔。
答案 2 :(得分:5)
根据您的需要,您仍然可以使用Handler完成您的任务。
你不必在while循环中创建/启动Handler(正如你所注意到的那样,除非你自己停止循环,否则只是堆叠起来,但这是无意义的。)
只需创建Handler并告诉他发布延迟的Runnable实例。在最后的Runnable中,您可以检查您的条件。如果它仍然正常,则发布另一个runnable延迟,否则你什么都不做,Handler将不再执行。
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("After 2 secs");
random_number = Math.random();
if (!stop) // should not be stopped, so we add another runnable;
{
handler.postDelayed(this, 2000);
}
}
handler.postDelayed(runnable, 2000);
唯一的缺点是如果设备暂时不使用,Handler可能会冻结,这意味着一旦打开设备屏幕,它将从它离开的位置开始计数。
它可以做1分钟正确的工作,然后在设备退出睡眠模式时阻止1.4秒,一旦再次打开,Handler将完成剩余的0.6秒。
但是,不知道您的需求,您可能不受此行为的影响,而答案可能适合您。
答案 3 :(得分:3)
如果你想使用线程,可以这样做:
Thread t = new Thread(){
public void run(){
while(true){
if(stop) break;
random_number = Math.random();
sleep(2000);
}
}
};
t.start();