Object中线程相关方法wait、notify、notifyAll分析


Object.wait()、Object.notify()、Object.notifyAll()必须要与synchronized一起使用,必须在synchronized方法内部或synchronized块内部使用。

wait

让当前线程进入等待(阻塞)WAITTING 状态,将线程放入到等待队列中,并释放对象锁。

需要注意:调用wait方法后,会立即释放当前线程锁占有的对象锁。会暂停执行wait后面的代码块,需要等待,其它拿到该锁对象的线程执行notify或notifyAll方法唤醒该线程后,才会继续执行wait后面的代码块。

三个wait方法的对比:

  1. wait()

    1. 不会自动被唤醒,需等其他占有该对象锁的线程调用锁对象的notify或notifyAll方法时才会被唤醒
  2. wait(long timeout)

    1. timeout(毫秒)时间后会被自动唤醒
    2. 其他占有该对象锁的线程调用锁对象的notify或notifyAll方法唤醒
  3. wait(long timeout, int nanos)

    1. nanos的范围为:0-999999
      1. 当nanos=0时,timeout(毫秒)时间后会被自动唤醒;
      2. 当0<nanos<=999999时,timeout+1(毫秒)时间后会被自动唤醒
    2. 其他占有该对象锁的线程调用锁对象的notify或notifyAll方法唤醒

wait(0)方法

wait(0)等同于wait()。

notify

从当前对象锁的等待队列中获取一个线程(如果有多个线程则获取优先级高的,优先级都一样则随机),移入到同步队列中,参与锁的竞争。

需要注意:调用notify方法后,当前线程不会马上释放该对象锁,要等到同步块或者同步方法执行完后,当前线程才会释放锁。

notifyAll

和notify一样,都是用来唤醒处于等待状态的线程参与锁的竞争,但也有一些区别。

notifyAll会将当前对象锁的等待队列的所有线程,都移入到同步队列中,但与锁的竞争。

需要注意:调用notifyAll方法后,当前线程不会马上释放该对象锁,要等到同步块或者同步方法执行完后,当前线程才会释放锁。

锁的释放问题

  1. wait会立即释放当前线程锁占有的对象锁;
  2. notify和notifyAll不会立即释放,会等到当前的同步块或同步方法执行完后,才会释放当前线程锁占有的对象锁。

经典示例

例:使用两个线程,顺序打印1-100的数字。

    public static void main(String[] args) {
        Object lock = new Object();
        AtomicInteger a = new AtomicInteger(1);
        Thread t1 = new Thread(() -> {
            synchronized (lock) {
                for (; a.get() <= 100; ) {
                    lock.notify();
                    System.out.println("Thread t1:" + a.get());
                    a.getAndIncrement();
                    if (a.get() >= 100) {
                        break;
                    }
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        Thread t2 = new Thread(() -> {
            synchronized (lock) {
                for (; a.get() <= 100; ) {
                    lock.notify();
                    System.out.println("Thread t2:" + a.get());
                    a.getAndIncrement();
                    if (a.get() >= 100) {
                        break;
                    }
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        
        t1.start();
        t2.start();
    }
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值