难度
初级
学习时间
30分钟
适合人群
零基础
开发语言
Java
开发环境
- JDK v11
- IntelliJIDEA v2018.3
友情提示
- 本教学属于系列教学,内容具有连贯性,本章使用到的内容之前教学中都有详细讲解。
- 本章内容针对零基础或基础较差的同学比较友好,可能对于有基础的同学来说很简单,希望大家可以根据自己的实际情况选择继续看完或等待看下一篇文章。谢谢大家的谅解!
1.温故知新
前面在 一章中介绍了 Lock 与Condition实战项目:从零手写一个线程安全缓冲区 。
在 一章中介绍了 用显式锁Lock与Condition对象来实现生产者与消费者模型 。
在 一章中介绍了 读写锁ReadWriteLock 。
在 一章中介绍了 读锁与写锁之间相互嵌套情况 。
在 一章中介绍了 可重入读写锁ReentrantReadWriteLock的获取线程与读写锁保持数系列方法 。
现在介绍 可重入读写锁ReentrantReadWriteLock的查询是否有线程正在等待获取读写锁hasQueuedThreads()方法、获取有多少个正在等待获取读写锁的线程getQueueLength()方法和查询指定线程是否正在等待获取读写锁的hasQueuedThread(Thread thread)方法。
2.查询是否有线程正在等待获取读锁或写锁hasQueuedThreads()方法
我们可以使用hasQueuedThreads()方法来查询是否有线程正在等待获取读锁或写锁。
请问这个方法有什么用呢?
我们可以用这个方法随时知道读写锁的状态,比如想关闭某个程序,但不确定程序中是否还有线程正在使用着读写锁(即还有任务没有执行完),我们就可以使用hasQueuedThreads()方法来查询了,当hasQueuedThreads()方法返回 false 时,说明已经没有线程正在使用读写锁了,这样我们就可以安然地关闭程序了。
hasQueuedThreads()方法在ReentrantReadWriteLock类中的 源码 :
将注释翻译成中文:
中文注释全文:
查询是否有线程正在等待获取读锁或写锁。
去掉注释版:
hasQueuedThreads()方法作用是查询是否有线程正在等待获取读锁或写锁,如果有线程正在等待获取读锁或写锁则返回true,否则返回false。
访问权限
public :hasQueuedThreads()方法是公开的。
final :hasQueuedThreads()方法是最终的,不支持重写。
boolean :hasQueuedThreads()方法返回boolean类型的值,如果有线程正在等待获取读锁或写锁则返回true,否则返回false。
hasQueuedThreads()方法只能被对象调用。
参数
无。
抛出的异常
无。
应用
下面,我们就来试试hasQueuedThreads()方法。
首先,创建出读写锁:
其次,创建出读锁和写锁:
然后,我们创建出任务,目的是让多个线程去执行同一个任务:
先不着急完善run()方法。
先来创建出3个线程,并把任务传递给这些线程:
接着,启动线程:
再来完善run()方法。
在run()方法中使用读写锁,大家可以两把锁一起用,也可以使用其中任意一把,这里我们只使用写锁好了:
在获取锁之后让线程睡N秒,这里时间大家也可以自定:
然后,我们在启动线程的代码后面调用hasQueuedThreads()方法并输出结果:
在输出结果之前让主线程睡1秒,这样做的目的是为了让主线程等这些线程都去等待锁,只有这些线程都去等待锁之后我们才可以看到hasQueuedThreads()方法的效果 :
例子书写完毕。
运行程序,执行结果:
从运行结果来看,符合预期。
我们不光可以查询是否有线程正在等待获取读锁或写锁,还可以查询到有多少个线程正在等待获取读锁或写锁。
3.查询有多少个线程正在等待获取读锁或写锁getQueueLength()方法
有时候,我们通过hasQueuedThreads()方法查询到有线程正在等待获取读写锁,但是我们不知道有多少个线程正在等待获取读写锁,于是可以使用getQueueLength()方法来获取。
getQueueLength()方法在ReentrantReadWriteLock类中的源码:
将注释翻译成中文:
中文注释全文:
查询有多少个线程正在等待获取读锁或写锁。
去掉注释版:
getQueueLength()方法作用是查询有多少个线程正在等待获取读锁或写锁,方法返回正在等待获取读锁或写锁的线程个数。
访问权限
public :getQueueLength()方法是公开的。
final :getQueueLength()方法是最终的,不支持重写。
int :getQueueLength()方法返回int类型的值,返回正在等待获取读锁或写锁的线程个数。
getQueueLength()方法只能被对象调用。
参数
无。
抛出的异常
无。
应用
下面,我们来试试getQueueLength()方法。
还是上一小节的例子,而且我们还要搭配着hasQueuedThreads()方法使用。
首先,将以下代码移除:
然后,判断是否有线程正在等待获取读写锁:
当有线程正在获取读写锁时,再获取有多少个线程正在等待获取读写锁:
例子改写完毕。
运行程序,执行结果:
从运行结果来看,符合预期。
虽然我们知道了有3个线程在竞争写锁,其中只有一个线程拿到写锁,还有另外两个线程正在等待写锁,但是我不知道哪两个线程正在等待写锁,有什么办法可以知道吗?
有,我们可以使用 hasQueuedThread(Thread thread) 方法来查询指定线程是否正在等待读写锁。
4.查询指定线程是否正在等待获取读写锁 hasQueuedThread(Thread thread)方法
前面我们使用hasQueuedThreads()方法查询了是否有线程正在等待获取读锁或写锁,又使用getQueueLength()方法获取到有多少线程正在等待读锁或写锁,接下来,我们再使用hasQueuedThread(Thread thread)方法来判断指定线程是否正在等待获取读锁或写锁。
hasQueuedThread(Thread thread)方法在ReentrantReadWriteLock类中的源码:
将注释翻译成中文:
中文注释全文:
查询指定线程是否正在等待获取读写锁。
去掉注释版:
hasQueuedThread(Thread thread)方法作用是查询指定线程是否正在等待获取读写锁,当指定线程正在等待获取读写锁时返回true,否则返回false。
访问权限
public :hasQueuedThread(Thread thread)方法是公开的。
final :hasQueuedThread(Thread thread)方法是最终的,不支持重写。
boolean :hasQueuedThread(Thread thread)方法返回boolean类型的值,当指定线程正在等待获取读写锁时返回true,否则返回false。
hasQueuedThread(Thread thread)方法只能被对象调用。
参数
thread :指定线程。
抛出的异常
无。
应用
下面,我们就来试试hasQueuedThread(Thread thread)方法。
还是上一小节的例子,我们接着输出语句(即当有线程正在等待获取读写锁时)后面写。
分别判断我们创建的3个线程是否正在等待获取读写锁:
例子改写完毕。
运行程序,执行结果:
从运行结果来看,符合预期。
我们3个线程其中有两个线程正在等待获取读写锁,分别是thread1和thread3。当然了,这个结果每次运行都有可能不一样,因为每个线程获取读写锁的机会是公平的,所以每个线程都有可能先获取到读写锁,而其他线程只有等待。
5.可以被多个线程同时拥有的读锁
为什么要把读锁单独拿出来说呢?
因为写锁在某一时刻最多只能被一个线程拥有,而读锁在某一时刻最多可以被多个线程拥有,所以我们不一定能够看到线程等待读锁的情况。
还是上一小节的例子,我们把读写换成读锁:
运行程序,执行结果:
从运行结果来看,不符合预期。程序停着不动了。
原因是什么呢?
是我们创建的3个线程都被睡了N秒:
这样,我们将其改为1秒:
再运行程序,执行结果:
从运行结果来看,符合预期。
程序什么都没输出,为什么说符合预期呢?
因为我们在这里判断了是否有线程正在等待获取读写锁,而程序中没有一个线程等待获取读锁,所以这里的判断条件为false,从而不执行if语句里面的内容,程序没有输出任何内容。
现在,我们可以把if条件语句移除掉,只保留if语句里面的内容看看:
再运行程序,执行结果:
从运行结果来看,符合预期。没有一个线程正在等待获取读锁。
大家以后在用这三个方法时,注意它们之间的搭配。
最后,希望大家可以把这个例子照着写一遍,然后再自己默写一遍,方便以后碰到类似的面试题可以轻松应对。
祝大家编码愉快!
GitHub
本章程序GitHub地址:
总结
- hasQueuedThreads()方法作用是查询是否有线程正在等待获取读锁或写锁,如果有线程正在等待获取读锁或写锁则返回true,否则返回false。
- getQueueLength()方法作用是查询有多少个线程正在等待获取读锁或写锁,方法返回正在等待获取读锁或写锁的线程个数。
- hasQueuedThread(Thread thread)方法作用是查询指定线程是否正在等待获取读写锁,当指定线程正在等待获取读写锁时返回true,否则返回false。
至此,Java中查询线程是否正在等待获取读写锁相关内容讲解先告一段落,更多内容请持续关注。
答疑
如果大家有问题或想了解更多前沿技术,请在下方留言或评论,我会为大家解答。
上一章
下一章
“全栈2019”Java多线程第四十四章:读锁不支持Condition
学习小组
加入同步学习小组,共同交流与进步。
- 方式一:关注头条号Gorhaf,私信“Java学习小组”。
- 方式二:关注公众号Gorhaf,回复“Java学习小组”。
全栈工程师学习计划
关注我们,加入“全栈工程师学习计划”。
版权声明
原创不易,未经允许不得转载!