美文网首页
Java中线程同步(二):wait¬ify

Java中线程同步(二):wait¬ify

作者: DON_1007 | 来源:发表于2017-03-02 18:18 被阅读0次

wait&notify是Object中就定义的方法,换句话就是说Java中所有的对象都支持这两个方法。当一个对象调用了wait方法之后,就会阻塞当前线程,如果想要代码继续执行,就需要在适当的时候调用notify。假设现在有两个线程A和B,同时运行,A先调用wait方法阻塞当前线程,等待着被B线程唤醒。

程序运行示意图
wait&notify.jpg

实现代码:

    private Object object = new Object();
    private static final String TAG = "ThreadRun";

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        RelativeLayout relativeLayout = new RelativeLayout(getActivity());
        return relativeLayout;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        //程序入口
        ThreadA threadA = new ThreadA();
        ThreadB threadB = new ThreadB();

        threadA.start();
        threadB.start();

    }

    private class ThreadA extends Thread{
        @Override
        public void run() {
            super.run();

            synchronized (object) {
                try {
                    Log.e(TAG, "Thread A start");
                    object.wait();//阻塞了当前线程,等待被唤醒
                    Log.e(TAG,"Thread A end");
                }catch (Exception e){
                    e.printStackTrace();
                }
            }

        }
    }

    private class ThreadB extends Thread{
        @Override
        public void run() {
            super.run();

            synchronized (object){
                try {
                    Log.e(TAG, "Thread B start");
                    Thread.sleep(1000);//一秒之后唤醒线程A
                    object.notify();//唤醒线程A
                    Log.e(TAG,"Thread B end");
                }catch (Exception e){
                    e.printStackTrace();
                }
            }

        }
    }

运行之后,控制台输出

03-02 18:13:39.369 13175-13199/? E/ThreadRun: Thread A start
03-02 18:13:39.369 13175-13200/? E/ThreadRun: Thread B start
03-02 18:13:40.369 13175-13200/? E/ThreadRun: Thread B end
03-02 18:13:40.369 13175-13199/? E/ThreadRun: Thread A end

与示意图相符。
这里需要特殊注意的是synchronized (object),synchronized 关键字是为了保证object在同一时间内只能被一个线程调用,在异步的线程A、B之间保证object的方法是同步执行的。

那么如果有多个线程同时调用了obje.wait()方法,那么该如何处理呢?Object类还有一个方法notifyAll(),它的作用就是唤醒所有在等待的线程。
现在新增加两个线程A1、A2

    private class ThreadA1 extends Thread{
        @Override
        public void run() {
            super.run();

            synchronized (object) {
                try {
                    Log.e(TAG, "Thread A1 start");
                    object.wait();//阻塞了当前线程,等待被唤醒
                    Log.e(TAG,"Thread A1 end");
                }catch (Exception e){
                    e.printStackTrace();
                }
            }

        }
    }

    private class ThreadA2 extends Thread{
        @Override
        public void run() {
            super.run();

            synchronized (object) {
                try {
                    Log.e(TAG, "Thread A2 start");
                    object.wait();//阻塞了当前线程,等待被唤醒
                    Log.e(TAG,"Thread A2 end");
                }catch (Exception e){
                    e.printStackTrace();
                }
            }

        }
    }

最开始调用的时候同样启动A1、A2

         //程序入口
        ThreadA threadA = new ThreadA();
        ThreadA1 threadA1 = new ThreadA1();
        ThreadA2 threadA2 = new ThreadA2();
        ThreadB threadB = new ThreadB();

        threadA.start();
        threadA1.start();
        threadA2.start();
        threadB.start();

在ThreadB中将 object.notify();修改为object.notifyAll();
运行程序

03-02 18:10:34.209 12882-12914/? E/ThreadRun: Thread A start
03-02 18:10:34.210 12882-12915/? E/ThreadRun: Thread A1 start
03-02 18:10:34.210 12882-12916/? E/ThreadRun: Thread A2 start
03-02 18:10:34.210 12882-12917/? E/ThreadRun: Thread B start
03-02 18:10:35.211 12882-12917/? E/ThreadRun: Thread B end
03-02 18:10:35.211 12882-12915/? E/ThreadRun: Thread A1 end
03-02 18:10:35.211 12882-12914/? E/ThreadRun: Thread A end
03-02 18:10:35.211 12882-12916/? E/ThreadRun: Thread A2 end

分析结果,A、A1、A2会执行,然后调用wait()被阻塞,接着执行B,B执行完之后notifyAll(),唤醒A、A1、A2,唤醒的顺序是无序的。

那么在多个线程同时在wait()的情况下如何通过notify()唤醒指定的线程呢?
JDK暂时还没有提供这样的方法,只知道notify会唤醒其中一个在等待的线程,具体是哪一个,并不确定。这一点在使用wait&notify来保持线程同步的时候需要注意。

相关文章

网友评论

      本文标题:Java中线程同步(二):wait¬ify

      本文链接:https://www.haomeiwen.com/subject/vpdkgttx.html