Java并发 Condition线程间通信
线程之间除了同步互斥,还要考虑通信。在Java5之前我们的通信方式为:wait 和 notify。Condition的优势是支持多路等待,即可以定义多个Condition,每个condition控制线程的一条执行通路。传统方式只能是一路等待
Condition提供不同于Object 监视器方法的行为和语义,如受保证的通知排序,或者在执行通知时不需要保持一个锁。
Condition实现可以提供Object监视器方法的行为和语义,例如有保证的通知顺序,或者在执行通知时不需要锁定。 如果一个实现提供了这样的专门的语义,那么实现必须记录这些语义。
需要注意的是Condition实例只是普通的对象,其本身作为一个目标synchronized语句,可以有自己的监视器wait和notification个方法调用。 获取Condition实例的监视器锁或使用其监视方法与获取与该Condition相关联的Condition或使用其waiting和signalling方法没有特定关系。 建议为避免混淆,您永远不会以这种方式使用Condition实例,除了可能在自己的实现之内。
除非另有说明,传递任何参数的null值将导致NullPointerException被抛出。
经典问题:三个线程依次打印ABC
package com.qf.Day814xw;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Clown 2019/8/14 15:07
* HAHAHAHAHAHAHA
*/
public class Alternative {
private int index = 1;//1 a 2 b 3 c
private Lock lock = new ReentrantLock();//一个可重入互斥Lock具有与使用synchronized方法和语句访问的隐式监视锁相同的基本行为和语义,但具有扩展功能。
Condition conditionA = lock.newCondition();//一个Condition实例本质上绑定到一个锁。
Condition conditionB = lock.newCondition();
Condition conditionC = lock.newCondition();
public void printA(){
lock.lock();
try {
if (index!=1){
try {
conditionA.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("A");
index=2;
conditionB.signal();
}finally {
lock.unlock();
}
}
public void printB(){
lock.lock();
try {
if (index!=2){
try {
conditionB.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("B");
index=3;
conditionC.signal();
}finally {
lock.unlock();
}
}
public void printC(){
lock.lock();
try {
if (index!=3){
try {
conditionC.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("C");
System.out.println("-----------------");
index=1;
conditionA.signal();
}finally {
lock.unlock();
}
}
}
package com.qf.Day814xw;
/**
* Clown 2019/8/14 15:04
* HAHAHAHAHAHAHA
*/
public class Test {
public static void main(String[] args) {
Alternative alternative = new Alternative();
new Thread(new Runnable(){
@Override
public void run() {
for (int i = 0; i < 20; i++) {
alternative.printA();
}
}
}).start();
new Thread(new Runnable(){
@Override
public void run() {
for (int i = 0; i < 20; i++) {
alternative.printB();
}
}
}).start();
new Thread(new Runnable(){
@Override
public void run() {
for (int i = 0; i < 20; i++) {
alternative.printC();
}
}
}).start();
}
}