Java多线程系列(4)--线程等待与唤醒

一、wait()、notify()、notifyAll()等方法基本概述

在Object.java中,定义了wait()、notify()和notifyAll()等接口。wait()的作用就是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的的锁;notify()是唤醒单个线程,而notifyAll()是唤醒所有的线程。
上述方法的详细信息如下:
notify() –唤醒在此对象监视器上等待的单个线程;
notifyAll() –唤醒在此对象监视器上等待的所有线程;
wait() —-让当前线程处于“等待(阻塞)状态”。直到其它线程调用此对象的notify()方法或者notifyAll()方法,当前线程被唤醒(进入就绪状态);
wait(long timeout) —-让当前线程处于“等待(阻塞)状态”。直到其它线程调用此对象的notify()方法或者notifyAll()方法,或者超过指定的时间量,当前线程被唤醒(进入就绪状态);
wait(long timeout,int nanos) —-让当前线程处于“等待(阻塞)状态”。直到其它线程调用此对象的notify()方法或者notifyAll()方法,或者超过指定的时间量,或者其它某个线程中断当前线程,当前线程被唤醒(进入就绪状态)
二、wait()、notify()、notifyAll()代码实例
由于与wait配合起来使用时,notify()和notifyAll()并无太大区别。下面仅通过wait与notify()代码来进行演示

package Test;

/**
 * Created by LKL on 2017/2/20.
 */
public class TestWaitAndNotify {
    public static void main(String[] args) throws InterruptedException {
        MyThread3 t1 = new MyThread3("t1");
     //   MyThread3 t2 = new MyThread3("t2");
        synchronized(t1){
            System.out.println(Thread.currentThread().getName()+" start t1");
         //   System.out.println(Thread.currentThread().getName()+" start t2");
            t1.start();
         //   t2.start();
            //主线程等待t1通过notify()唤醒
            System.out.println(Thread.currentThread().getName()+" wait() ");
            t1.wait();
            //此时持有t1这个对象的锁的是object

            System.out.println(Thread.currentThread().getName()+" continue ");
        }
    }
}


package Test;

/**
 * Created by LKL on 2017/2/20.
 */
public class MyThread3 extends Thread{
    public MyThread3(String name) {
        super(name);
    }
    public void run(){
        synchronized(this){
            System.out.println(Thread.currentThread().getName()+" call notify()");
            //唤醒当前线程
            notify();
        }
    }
}

运行结果如下:

main start t1
main wait() 
t1 call notify()
main continue 

上述流程为:
(1)主线程main通过new MyThread3(“t1”)新建线程t1,接着通过synchronized(t1)获取”获取t1对象的同步锁”,然后调用t1.start()启动线程t1。
(2)主线程main执行t1.wait()释放”t1对象的锁”,并且进入了等待(阻塞)状态。等待t1对象上的线程通过notify()或notifyAll()将其唤醒。
(3)线程t1运行之后,通过synchronized(this)获取”当前对象的锁”;接着调用notify()唤醒”当前对象上的得带线程”,此时也就意味着唤醒主线程;
(4)线程t1运行完毕之后,会释放当前对象的锁,接着,主线程获取t1对象的锁,然后接着运行。
当把上述代码修改如下时:

package Test;

/**
 * Created by LKL on 2017/2/20.
 */
public class TestWaitAndNotify {
    public static void main(String[] args) throws InterruptedException {
        MyThread3 t1 = new MyThread3("t1");
     //   MyThread3 t2 = new MyThread3("t2");
        synchronized(t1){
            System.out.println(Thread.currentThread().getName()+" start t1");
         //   System.out.println(Thread.currentThread().getName()+" start t2");
         //   t1.start();
         //   t2.start();
            //主线程等待t1通过notify()唤醒
            System.out.println(Thread.currentThread().getName()+" wait() ");
            t1.wait();
            //此时持有t1这个对象的锁的是object

            System.out.println(Thread.currentThread().getName()+" continue ");
        }
    }
}

也就是不开启t1这个线程,此时主线程main运行了t1.wait()后,一直处于阻塞状态,因为并没有线程将它唤醒。

main start t1
main wait() 

二、wait()、notify()总结

wait()会使当前线程等待,因为线程进入等待(阻塞)状态,所以线程应该释放它所持有的“同步锁”,否则其它线程获取不到这个“同步锁”而无法运行。
notify()和wait()直接就是依据“对象的同步锁”关联起来的。
假设我们把负责唤醒等待线程的那个线程称为唤醒线程,它只有在获取“该对象的同步锁”,此时的同步锁必须和等待线程的同步锁是同一个,并且调用notify()或调用notifyAll()方法之后,才能唤醒等待线程;但是它不能立刻执行,因为唤醒线程还持有该对象的同步锁,必须等到唤醒线程释放了对象的同步锁之后,等待线程才能获取到对象的同步锁,从而继续运行。
因此,notify()和wait()依赖于同步锁,而同步锁是对象所持有,并且每个对象只有一个。所以,wait()、notify()等方法定义在object类中,而不是Thread类中。

文章只是作为自己的学习笔记,借鉴了网上的许多案例,如果觉得阔以的话,希望多交流,在此谢过…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值