我是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();
  }

最佳答案

我猜stopThread的初始值为false,这将导致您的第二个循环无法执行,并且线程终止。

您可以在两个按钮之间共享一些锁定对象,而不必使用循环,而可以使用wait and 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

10-07 19:44
查看更多