“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

159 阅读9分钟

难度

初级

学习时间

30分钟

适合人群

零基础

开发语言

Java

开发环境

  • JDK v11
  • IntelliJIDEA v2018.3

友情提示

  • 本教学属于系列教学,内容具有连贯性,本章使用到的内容之前教学中都有详细讲解。
  • 本章内容针对零基础或基础较差的同学比较友好,可能对于有基础的同学来说很简单,希望大家可以根据自己的实际情况选择继续看完或等待看下一篇文章。谢谢大家的谅解!

1.温故知新

前面在《“全栈2019”Java多线程第四十六章:判断任意线程是否已持有写锁》一章中介绍了如何判断任意线程是否已持有写锁。通过ReentrantReadWriteLock的isWriteLocked()方法来判断写锁是否已被任意线程持有。

《“全栈2019”Java多线程第四十七章:判断锁是否为公平锁isFair()》一章中介绍了如何判断锁是否为公平锁isFair()方法。

《“全栈2019”Java多线程第四十八章:读写锁实战高并发容器》一章中介绍了如何使用读写锁实战简易版高并发容器。

《“全栈2019”Java多线程第四十九章:LockSupport简单介绍》一章中介绍了LockSupport的阻塞线程park()方法和唤醒线程unpark()方法

《“全栈2019”Java多线程第五十章:设置/获取LockSupport同步对象》一章中介绍了LockSupport的设置同步对象park​(Object blocker)方法和获取同步对象getBlocker​(Thread t)方法

现在介绍LockSupport的超时自动唤醒阻塞线程parkNanos​(long nanos)方法和可设置同步对象的超时自动唤醒阻塞线程parkNanos​(Object blocker, long nanos)方法

2.超时自动唤醒阻塞线程parkNanos​(long nanos)方法

之前在《“全栈2019”Java多线程第四十九章:LockSupport简单介绍》一章中介绍了park()方法,park()方法可以使当前线程阻塞,但被阻塞的线程只能被中断或被unpark(Thread thread)方法唤醒

接下来,为大家介绍一个park()方法的重载方法:parkNanos​(long nanos)方法。

parkNanos​(long nanos)方法可以设置当线程超过指定等待时间时可自动唤醒

parkNanos​(long nanos)方法解决了阻塞线程在超时这块的情况。

parkNanos​(long nanos)方法在LockSupport类中的源码:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

将注释翻译成中文:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

中文注释全文:

超时自动唤醒阻塞线程,被阻塞的线程也可以被中断或被unpark(Thread thread)方法唤醒。

去掉注释版:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

parkNanos​(long nanos)方法作用是超时自动唤醒阻塞线程,被阻塞的线程也可以被中断或被unpark(Thread thread)方法唤醒

访问权限

public:parkNanos​(long nanos)方法是公开的。

static:parkNanos​(long nanos)方法是静态的。

void:parkNanos​(long nanos)方法无返回值。

parkNanos​(long nanos)方法只能被类调用。

参数

nanos:等待的最大纳秒数。

抛出的异常

无。

应用

其实parkNanos​(long nanos)方法和park()方法作用是一样的,都是阻塞当前线程。只不过parkNanos​(long nanos)方法可以指定被阻塞的线程超时时间,当被阻塞线程等待的时间超过指定的等待的最大纳秒数时,被阻塞的线程自动唤醒。

当然了,如果被阻塞线程在等待时间之前被唤醒更好。

下面,我们就来试试parkNanos​(long nanos)方法。

首先,创建一个线程并重写run()方法:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

然后,在run()方法里面调用parkNanos​(long nanos)方法,这里指定等待的最大时间为1000000000纳秒(即1秒)

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

线程在1秒钟之后会自动醒来。

注意,parkNanos​(long nanos)方法传入的是纳秒数,不是秒数。

1秒 = 1000000000纳秒。

我们先使用这种笨办法将数字输入进去,待会教大家一个简单而且还一目了然的写法。

接着,在线程被阻塞前后各输出一句话,目的是为了看清楚线程何时被阻塞和何时被唤醒:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

最后,我们启动线程:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

例子书写完毕。

运行程序,执行结果:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

从运行结果来看,符合预期。线程在阻塞1秒钟之后自动唤醒。

3.时间单位转换TimeUnit.SECONDS.toNanos(long duration)方法

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

前面是用的是1秒 = 1000000000纳秒这种写法。

这种写法阅读性很差,不能一眼就看出时间有多长,还得数,数完还得转换,麻烦!

接下来,我们来换一种更一目了然的写法。

还是上一小节的例子,只不时间要过换一种写法:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

我们使用TimeUnit.SECONDS.toNanos(long duration)方法将需要转换的秒数换成纳秒数。这种方法不仅简便而且还有很好的阅读性。

强烈推荐大家使用TimeUnit.SECONDS.toNanos(long duration)方法设置超时时间。

例子改写完毕。

运行程序,执行结果:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

从运行结果来看,符合预期。时间虽换了一种写法,结果却未改变,很赞。

4.中断线程

通过parkNanos​(long nanos)方法阻塞的线程,不光可以自己超时被唤醒,而且还可以我们手动中断它

下面,我们就来试试中断被parkNanos​(long nanos)方法阻塞的线程。

还是上一小节的例子,这里先将等待的时间设置为5秒钟:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

然后,我们在启动线程之后调用线程的方法中断线程:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

最后,我们希望延时1秒钟之后再中断线程,所以在中断线程之前使当前线程睡1秒钟:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

例子改写完毕。

运行程序,执行结果:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

从运行结果来看,符合预期。被parkNanos​(long nanos)方法阻塞的线程也是可以被中断的

5.唤醒被阻塞的线程unpark(Thread thread)方法

我们不光可以使用中断线程的方式让阻塞中的线程醒过来,还可以使用unpark​(Thread thread)方法让阻塞中的线程醒过来。

unpark​(Thread thread)方法之前在《“全栈2019”Java多线程第四十九章:LockSupport简单介绍》一章中介绍过,这里就不再赘述,不清楚的小伙伴请前去查阅。

下面,我们就来试试unpark​(Thread thread)方法。

还是上一小节例子,只不过我们将中断线程的代码换成unpark​(Thread thread)方法:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

例子改写完毕。

运行程序,执行结果:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

从运行结果来看,符合预期。被parkNanos​(long nanos)方法阻塞的线程也是可以被unpark​(Thread thread)方法唤醒的

6.可设置同步对象的超时自动唤醒阻塞线程parkNanos​(Object blocker, long nanos)方法

前面演示了使用parkNanos​(long nanos)方法让线程阻塞并可以设置等待的最大纳秒数,但是parkNanos​(long nanos)方法不能设置同步对象。

之前在《“全栈2019”Java多线程第五十章:设置/获取LockSupport同步对象》一章中介绍了park​(Object blocker)方法可以设置同步对象

那么有没有一个既可以设置同步对象,又可以设置等待的最大纳秒数的方法呢?

有,那就是parkNanos​(Object blocker, long nanos)方法。

parkNanos​(Object blocker, long nanos)方法既可以设置同步对象,又可以设置线程等待的最大纳秒数。

parkNanos​(Object blocker, long nanos)方法在LockSupport类中的源码:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

将注释翻译成中文:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

中文注释全文:

超时自动唤醒阻塞线程,被阻塞的线程也可以被中断或被unpark(Thread thread)方法唤醒,方法可设置对象。

去掉注释版:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

parkNanos​(Object blocker, long nanos)方法作用是超时自动唤醒阻塞线程,被阻塞的线程也可以被中断或被unpark(Thread thread)方法唤醒,方法可设置对象。

访问权限

public:parkNanos​(Object blocker, long nanos)方法是公开的。

static:parkNanos​(Object blocker, long nanos)方法是静态的。

void:parkNanos​(Object blocker, long nanos)方法无返回值。

parkNanos​(Object blocker, long nanos)方法只能被类调用。

参数

blocker:同步对象。

nanos:等待的最大纳秒数。

抛出的异常

无。

应用

其实parkNanos​(Object blocker, long nanos)方法和park()方法、park​(Object blocker)方法以及parkNanos​(long nanos)方法作用都是一样的,都是阻塞当前线程,只不过它们各自可设置的东西不一样。

下面,我们就来用一用parkNanos​(Object blocker, long nanos)方法。

还是上一小节的例子。

因为parkNanos​(Object blocker, long nanos)方法需要一个同步对象,所以我们先创建出这个同步对象:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

然后,我们将parkNanos​(long nanos)方法换成parkNanos​(Object blocker, long nanos)方法,并将时间改为1秒钟:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

最后,将启动线程后面所有代码都移除掉:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

移除之后的完整代码:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

例子改写完毕。

运行程序,执行结果:

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

从运行结果来看,符合预期。线程被阻塞后1秒钟自动唤醒

使用parkNanos​(Object blocker, long nanos)方法阻塞的线程可以被中断或被唤醒,因为parkNanos​(Object blocker, long nanos)方法和parkNanos​(long nanos)方法作用一样,所以中断线程和使用unpark​(Thread thread)方法唤醒线程就不再重复演示了,请大家的谅解!

最后,希望大家可以把这个例子照着写一遍,然后再自己默写一遍,方便以后碰到类似的面试题可以轻松应对。

祝大家编码愉快!

GitHub

本章程序GitHub地址:https://github.com/gorhaf/Java2019/tree/master/Thread/LockSupport

总结

  • parkNanos​(long nanos)方法作用是超时自动唤醒阻塞线程,被阻塞的线程也可以被中断或被unpark(Thread thread)方法唤醒。
  • parkNanos​(Object blocker, long nanos)方法作用是超时自动唤醒阻塞线程,被阻塞的线程也可以被中断或被unpark(Thread thread)方法唤醒,方法可设置对象。

至此,Java中LockSupport中的parkNanos​(long nanos)方法和parkNanos​(Object blocker, long nanos)方法相关内容讲解先告一段落,更多内容请持续关注。

答疑

如果大家有问题或想了解更多前沿技术,请在下方留言或评论,我会为大家解答。

上一章

“全栈2019”Java多线程第五十章:设置/获取LockSupport同步对象

下一章

“全栈2019”Java多线程第五十二章:LockSupport等待截止时间

学习小组

加入同步学习小组,共同交流与进步。

  • 方式一:关注头条号Gorhaf,私信“Java学习小组”。
  • 方式二:关注公众号Gorhaf,回复“Java学习小组”。

全栈工程师学习计划

关注我们,加入“全栈工程师学习计划”。

“全栈2019”Java多线程第五十一章:LockSupport线程等待时间

版权声明

原创不易,未经允许不得转载!