美文网首页
wait() 和 notify()

wait() 和 notify()

作者: gczxbb | 来源:发表于2019-08-03 00:43 被阅读0次

    一、阻塞和恢复

    • Thread#sleep方法
    • 阻塞式IO方法
    • 获取同步锁失败,(锁被其他线程占用)
    • Object#wait方法。
    • sleep到达时间
    • 阻塞方法返回
    • 成功获取锁
    • Object#nofity方法

    二、wait()与notify()方法

    sleep()方法,Thread类,静态方法,线程休眠指定时间(参数)。
    wait()方法,Object类,对象方法,本线程休眠。

    public class WaitNotifyRunnable implements Runnable {
        public static final String TAG = "WaitNotifyRunnable";
    
        public void secondMethod() throws Exception {
            String threadName = Thread.currentThread().getName();
            Thread.sleep(2000);//
            Log.d(TAG, threadName + "线程:secondMethod()方法");
            synchronized (this) {
                Log.d(TAG, threadName + "线程,竞争获得锁,进入休眠" );
                Thread.sleep(10000);//不会释放锁
                Log.d(TAG, threadName + "线程,通知唤醒wait线程" );
                notifyAll();
                Thread.sleep(5000);//不会释放锁
            }
        }
    
        public void run() {
            try {
                String threadName = Thread.currentThread().getName();
                Log.d(TAG, threadName + "线程:run()方法");
                synchronized (this) {
                    Log.d(TAG, threadName + "线程,竞争获得锁,进入休眠" );
                    this.wait();//释放锁。
                    Log.d(TAG, threadName+"线程,被唤醒" );
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    第一个是run方法,第二个方法外部线程调用,示例中共启动四个线程,并发执行。
    wait()方法必须在同步代码中,sleep()方法可以在任何地方。

    //wait_notify
    public static void startWaitNotify() {
        //线程1
        final WaitNotifyRunnable taskRunnable = new WaitNotifyRunnable();
        Thread thread = new Thread(taskRunnable);
        thread.start();
        Thread thread2 = new Thread(taskRunnable);
        thread2.start();
        Thread thread3 = new Thread(taskRunnable);
        thread3.start();
    
        //线程4
        Thread second = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    taskRunnable.secondMethod();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        second.start();
    }
    

    前三个线程并发执行任务,run方法,每一个进入synchronized()的线程对Runnable对象加锁。
    wait方法,线程进入休眠,同时释放锁,三个并发线程轮流竞争到锁进入同步代码块并wait()休眠。
    第四个线程执行任务的secondMethod方法,和前三个线程是同一个对象锁。先执行2s休眠。
    前三个线程的wait()方法会释放锁,当第四个线程获得锁,sleep方法,不会释放锁。sleep()方法,时间自动唤醒,不需要notify通知唤醒。
    当第四个线程执行nofity()方法,唤醒其中一个wait()方法休眠的线程,线程四继续休眠,未释放锁,此时,被唤醒线程需要等待锁。再等待sleep(5000)5s,释放锁,竞争获取锁继续执行。

    20225-20273/com.gc.multi D/WaitNotifyRunnable: Thread-2线程,竞争获得锁,进入休眠
    20225-20274/com.gc.multi D/WaitNotifyRunnable: Thread-3线程,竞争获得锁,进入休眠
    20225-20275/com.gc.multi D/WaitNotifyRunnable: Thread-4线程,竞争获得锁,进入休眠
    
    //第四个线程获得锁
    20225-20276/com.gc.multi D/WaitNotifyRunnable: Thread-5线程,竞争获得锁,进入休眠
    20225-20276/com.gc.multi D/WaitNotifyRunnable: Thread-5线程,sleep结束,通知唤醒wait线程
    20225-20276/com.gc.multi D/WaitNotifyRunnable: Thread-5线程,即将再次sleep,不会释放锁,被唤醒的wait,进入锁等待池
    
    //第四个线程notify通知唤醒,sleep未释放锁,继续休眠后释放。
    20225-20274/com.gc.multi D/WaitNotifyRunnable: Thread-3线程,被唤醒
    20225-20273/com.gc.multi D/WaitNotifyRunnable: Thread-2线程,被唤醒
    20225-20275/com.gc.multi D/WaitNotifyRunnable: Thread-4线程,被唤醒
    

    nofity()方法,仅唤醒一个wait()方法的休眠线程。nofityAll()方法,唤醒所有wait()线程。

    三、join()与yield()方法

    join()方法,在一个线程A中调用另一个线程B的join()方法,A线程将等待B线程执行完毕再执行。
    yield()方法,当线程执行了该方法,是线程从运行状态转换就绪状态,把运行机会交给其他具有相同优先级的线程,不是阻塞,出让cpu后,该线程再一次轮转仍然有可能被cpu选中执行。

    四、总结

    sleep方法,Thread类的静态方法,wait方法,Object对象的方法。

    wait方法只能在同步代码块或同步方法,sleep方法使用在任何地方。

    两个方法都会使当前线程让出CPU,wait方法会释放对象锁,sleep方法不会。

    sleep方法在到达时间时,自动唤醒,wait需要notify通知唤醒,进入对象锁定池,再次获得对象锁才能继续执行。

    线程的interrupt()方法会打断休眠状态(wait和sleep),抛出InterruptedException异常。


    任重而道远

    相关文章

      网友评论

          本文标题:wait() 和 notify()

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