JUC中的线程通信 Condition
Posted XeonYu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JUC中的线程通信 Condition相关的知识,希望对你有一定的参考价值。
上一篇:
上一篇文章我们简单用了下ReentrantLock。
我们知道,用synchronized的时候,我们可以通过Object类中的wait和notify来实现线程间的通信。但是wait和notify只能在synchronized中使用,那使用Lock时如何实现线程通信呢?
Condition
Condition是一个接口,他就是替代Object中的wait和notify方法来解决使用Lock时线程间的通信问题。
Condition要比Object中的wait和notify更加灵活一些,且能实现更加复杂的业务。
我们先来简单用一用Condition
有一下代码:
class MyNumber {
private final ReentrantLock lock = new ReentrantLock();
/*条件*/
private final Condition condition = lock.newCondition();
/*默认值为0*/
private int number = 0;
/*加操作*/
public void add() {
lock.lock();
try {
String name = Thread.currentThread().getName();
while (number == 1) {
/*当值为不为0时 等待其他线程将值变为变为0*/
condition.await();
}
/*值为0时 加一*/
number++;
System.out.println(name + "加一:" + number);
/*通知其他个线程可以做减一操作了*/
condition.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
public void reduce() {
lock.lock();
String name = Thread.currentThread().getName();
try {
/*值为0时 等待*/
while (number == 0) {
condition.await();
}
/*不为0时 减一*/
number--;
System.out.println(name + "减一:" + number);
/*通知其他线程可以做加一操作了*/
condition.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}
这个Number类有两个方法,加一和减一。
main方法如下:
public static void main(String[] args) {
MyNumber number = new MyNumber();
new Thread(() -> {
for (int i = 0; i < 5; i++) {
number.add();
}
}, "线程1").start();
new Thread(() -> {
for (int i = 0; i < 5; i++) {
number.reduce();
}
}, "线程2").start();
}
运行一下:
可以看到,符合预期,线程之间的通信是没有问题的。
再加2个线程试一下:
public static void main(String[] args) {
MyNumber number = new MyNumber();
new Thread(() -> {
for (int i = 0; i < 5; i++) {
number.add();
}
}, "线程1").start();
new Thread(() -> {
for (int i = 0; i < 5; i++) {
number.reduce();
}
}, "线程2").start();
new Thread(() -> {
for (int i = 0; i < 5; i++) {
number.add();
}
}, "线程3").start();
new Thread(() -> {
for (int i = 0; i < 5; i++) {
number.reduce();
}
}, "线程4").start();
}
运行来看一下:
发现运行结果没有走完,且卡死了。
原因是signal跟notify一样,当有多个线程都处于等待中,只会唤醒其中一个,另一个就一直处于等待中,最终就会出现四个线程都在等待被唤醒,造成死锁
所以,如果有多个线程时,一定要全部唤醒,以免出现死锁。
将signal改为 signalAll 即可
改好后再来运行一下:
可以看到,这下运行就正常了。
Condition暂时就是这些。
如果你觉得本文对你有帮助,麻烦动动手指顶一下,可以帮助到更多的开发者,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!
以上是关于JUC中的线程通信 Condition的主要内容,如果未能解决你的问题,请参考以下文章