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

时间:2015-03-04 00:00:23

标签: java android multithreading wait 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--);
         }

    }
}

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

略有修改的代码:

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中公开。将活动用作监视器是非常糟糕的主意。在任何地方传递活动的参考是非常糟糕的主意。
  3. 您使用了不同的监视器对象:ThreadActivity。使用一个内部线程。