《Java并发编程之美》- 线程中wait的用法

线程中wait的用法

Thread thread_d = new Thread(() -> {
            synchronized (resourceA) {
                System.out.println("thread_d get resourceA Lock");
                for (int i = 0; i < 100; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if(i==5) {
                        try {
                            //让该线程等待阻塞 5 秒中后重新获取锁对象
                            resourceA.wait(1000*5);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("thread_d ===> " + i);
                }
            }
        }, "thread_d");
​
        Thread thread_e = new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (resourceA) {
                System.out.println("tread_e get resourceA Lock");
                for (int i = 0; i < 10; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if(i==6){
                        try {
                            resourceA.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("thread_e ===> " + i);
                }
            }
        }, " thread_e");

如果启动上面两个线程会发生什么现象呢?

首先线程 thread_d 启动,1秒钟后线程 thread_e 启动,并且线程 thread_d 优先获取锁共享变量锁 resourceA ,在 5 秒中后,线程 thread_d 释放锁资源处于阻塞状态,线程 thread_e 获得锁资源,在 5 秒中后,线程 thread_b 释放锁资源,同时进入阻塞状态。此时线程 thread_d 已经被唤醒处于就绪状态,等待抢夺 thread_b 释放的 共享变量锁 resourceA ,当 thread_d 重新抢夺获取资源后,线程 thread_d 重新进入运行状态。

关于 wait 的几种方法

    public final void wait() throws InterruptedException {
        wait(0);
    }
    public final native void wait(long timeout) throws InterruptedException;
    public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }
​
        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }
​
        if (nanos > 0) {
            timeout++;
        }
​
        wait(timeout);
    }

比较有意思的是 wait(long timeout ,int nanos) 这个方法

官方给出的解释是,为了更加精准的控制并发的时间后面的 参数 nanos 只要 满足大于 0 并且小于 999999 这个条件,(1毫秒 = 1000 微秒 = 1000 000 纳秒)就在原先的等待时间上加 1 毫秒。

早起的 jdk 中关于 wait(long timeout ,int nanos) 方法

public final void wait(long timeout, int nanos) throws nterruptedException {
    if (timeout < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }
    // nanos 单位为纳秒,  1毫秒 = 1000 微秒 = 1000 000 纳秒
    if (nanos < 0 || nanos > 999999) {
        throw new IllegalArgumentException(
                "nanosecond timeout value out of range");
    }
​
    // nanos 大于 500000 即半毫秒  就timout 加1毫秒
    // 特殊情况下: 如果timeout为0且nanos大于0,则timout加1毫秒
    if (nanos >= 500000 || (nanos != 0 && timeout == 0)) {
        timeout++;
    }
​
    wait(timeout);
}

【思考】

其实个人感觉,这里的 nanos 其实很没有意思,就目前常用的 1.8 JDK 中 wait 方法 nanos 参数的判断范围为(0-999999),那么只要传入的参数值在这个范围内,原先的延时时间都是加 1 毫秒,这就显得 nanos 这个参数无任何实质性的意义了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值