Android 线程无法使用 wait() 和 notify() 使 notify() 正常工作

Android threads can't get notify() to work properly using wait() and notify()

所以我正在编写一个 Android 应用程序,它会在用户按下按钮时进行倒计时。线程运行倒计时。我的问题是,当我暂停应用程序时,我希望线程停止计数,然后在应用程序返回后恢复。我的通知无法正常工作。帮忙谢谢!

public class MainActivity extends Activity {
    private TextView mText;
    private EditText mUserInput;
    private CounterThread mCounterThread;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mText = (TextView)findViewById(R.id.text);
    mUserInput = (EditText)findViewById(R.id.userInput);
    mCounterThread = new CounterThread();
}

@Override
public synchronized void onPause(){
    super.onPause();
    mCounterThread.running = false;
}

@Override
public synchronized void onResume(){
    super.onResume();
    mCounterThread.running = true;
    notify();//seems like this does nothing!
}

public void startCounterThread(){
    mCounterThread.start();
}

public void button_handler(View v){
    startCounterThread();
   }

public void updateSeconds(final long seconds){
    Runnable UIdoWork = new Runnable(){
        public void run(){
            String time = String.valueOf(seconds);
            mText.setText("Your file will open in " + time + " seconds");
        }
    };
    runOnUiThread(UIdoWork);
}

private class CounterThread extends Thread{
    int count = 10;
    boolean running = true;

    @Override
    public synchronized void run(){
        while(count != 0){
            while(!running){
                try{
                    wait();//wait() will wait forever
                    //I don't want to put a time since 
                    //I have no clue when the user will resume again
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }

            try{
                Thread.sleep(1000);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            updateSeconds(count--);
         }

    }
}

这不起作用是有道理的,因为 wait() 和 notify() 在用作锁的对象上工作。当您在 运行() 方法中 运行 wait() 时,您使用的是 CounterThread 的实例作为锁,但是当您在 onResume() 方法中 运行 notify() 时,您正在使用 MainActivity 的一个实例。 CounterThread 永远不会收到通知。您的选择是(在您的 onResume() 方法中):

...
synchronized(mCounterThread) {
    mCounterThread.notify();
}
...

稍微修改的代码:

public class MainActivity extends Activity {
    private TextView mText;
    private EditText mUserInput;
    private CounterThread mCounterThread;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_2);
        mText = (TextView) findViewById(R.id.text);
        mUserInput = (EditText) findViewById(R.id.userInput);
        mCounterThread = new CounterThread();
        mCounterThread.start();
    }

    @Override
    public synchronized void onPause() {
        super.onPause();
        mCounterThread.onPause();
    }

    @Override
    public synchronized void onResume() {
        super.onResume();
        mCounterThread.onResume();
    }

    public void startCounterThread() {
        mCounterThread.start();
    }

    public void button_handler(View v) {
        startCounterThread();
    }

    public void updateSeconds(final long seconds) {
        Runnable UIdoWork = new Runnable() {
            public void run() {
                String time = String.valueOf(seconds);
                mText.setText("Your file will open in " + time + " seconds");
            }
        };
        runOnUiThread(UIdoWork);
    }

    private class CounterThread extends Thread {
        private int count = 10;
        private final Object lock = new Object();
        private volatile boolean isRunning = true;

        public void onResume() {
            if(!isRunning){
                isRunning = true;
                synchronized (lock){
                    lock.notify();
                }
            }

        }

        public void onPause() {
            isRunning = false;
        }

        @Override
        public void run() {
            while (count != 0) {

                synchronized (lock) {

                    if (!isRunning) try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        //
                    }
                }


                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    //
                }
                updateSeconds(count--);
            }

        }
    }
}
  1. 您的字段 running 必须标记为 volatile。它基本上意味着多个线程可以更改它并且所有线程都会看到它。
  2. 不要从 ThreadRunnable 中公开监视器对象。使用 activity 作为监视器是非常糟糕的主意。在任何地方传递 activity 的引用是非常糟糕的主意。
  3. 您使用了不同的监视器对象:ThreadActivity。使用一根内螺纹。