Android 线程无法使用 wait() 和 notify() 让 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--);
         }
    }
}

轻微修改的代码:

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用作监视器是个坏主意。把活动的参考传递到任何地方都是个坏主意
  3. 您使用了不同的监视器对象:ThreadActivity。使用一个内螺纹

不工作是有道理的,因为wait()和notify()处理的是用作锁的对象。当您在run()方法中运行wait()时,您使用的是CounterThread的实例作为锁,但当您在onResume()方法内运行notify()时时,您正在使用MainActivity的实例。CounterThread永远不会收到通知。您的替代方案是(在onResume()方法中):

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

最新更新