我是Threads的新手,在代码中使用线程时遇到以下问题。
在按钮上单击我正在启动运行特定任务的线程,并且此任务在系统后台运行。我在线程内使用while循环来检查是否通过另一个按钮单击更改了挥发性布尔值以停止整个过程。问题是我必须添加一个空循环,否则看起来线程会自行停止并且不再检查while条件。我认为这效率很低并且浪费大量资源。
我要添加一个简短的代码版本,以减少可读性。
您知道为什么会发生这种情况以及如何提高代码的整体效率吗?
public void onClick(View view) {
new Thread(new Runnable() {
public void run() {
//execute my task
while(!stopThread) {
// Without this empty loop the thread stops after a while
}
while(stopThread) { // stopThread is a volatile bool changed by another button click
//Finish the task
break;
}
}
}).start();
}
答案 0 :(得分:2)
我猜想stopThread的初始值为false,这将导致您的第二个循环无法执行,并且线程终止。
代替使用循环,您可以在两个按钮之间共享一些锁定对象,并使用wait和notify代替。选中this tutorial
。
可能的实现看起来像这样:
两个按钮都需要访问这两个变量:
Object lock = new Object();
volatile boolean stopThread = false;
第一个按钮的onClick
方法:
public void onClick(View view) {
new Thread(new Runnable() {
public void run() {
// execute my task
synchronized (lock) {
// stopThread is a volatile boolean changed by another button click
while (stopThread == false) {
lock.wait();
}
}
// Finish the task
}
}).start();
}
第二个按钮的onClick
方法:
public void onClick(View view) {
new Thread(new Runnable() {
public void run() {
synchronized (lock) {
stopThread = true;
lock.notify();
}
}
}).start();
}
您将需要保留布尔标志以处理spurious wakeups
。如果条件已满足,请继续执行代码,否则请返回以等待通知。
请注意,该示例并未处理可能发生的任何中断。
您可能想使用AsyncTask.execute
而不是自己启动线程。
选中此answer
。