用juc包里lock+await+signal的组合替换传统的synchronized+wait+notify,以实现精准通知,精准唤醒
场景:
有三种线程A,B,C,让它们轮流打印:A打印5遍“我是A”,B打印10遍“我是B”,C打印15遍“我是C”,A打印5遍“我是A”…这样交替打印。
现假设A,B,C各有10个线程
代码:
/**
*
* @ClassName: Printer
* @Description: 打印机资源类
* @author: fuling
* @date: 2020年9月10日 下午12:37:39
*/
class Printer{
private int flag = 1; //标志位,表示当前应该轮到哪种线程打印
private Lock lock = new ReentrantLock(); //一把资源锁
private Condition condition1 = lock.newCondition(); //A类线程拥有的资源锁钥匙1
private Condition condition2 = lock.newCondition(); //B类线程拥有的资源锁钥匙2
private Condition condition3 = lock.newCondition(); //C类线程拥有的资源锁钥匙3
/**
*
* @Title: printA
* @Description: A类线程的打印操作
* @return: void
*/
public void printA() {
lock.lock();
try {
//判断是否轮到A线程打印
while(this.flag != 1) {
condition1.await();
}
//A线程开始打印
for(int i = 0; i < 5; i++) {
System.out.println("我是A线程");
}
//A线程打印完毕,标识位置为2,唤醒B种类的线程
this.flag = 2;
condition2.signalAll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
lock.unlock();
}
}
/**
*
* @Title: printB
* @Description: B类线程的打印操作
* @return: void
*/
public void printB() {
lock.lock();
try {
//判断是否轮到B线程打印
while(this.flag != 2) {
condition2.await();
}
//B线程开始打印
for(int i = 0; i < 10; i++) {
System.out.println("我是B线程");
}
//B线程打印完毕,标识位置为3,唤醒C种类的线程
this.flag = 3;
condition3.signalAll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
lock.unlock();
}
}
/**
*
* @Title: printC
* @Description: C类线程的打印操作
* @return: void
*/
public void printC() {
lock.lock();
try {
//判断是否轮到C线程打印
while(this.flag != 3) {
condition3.await();
}
//C线程开始打印
for(int i = 0; i < 15; i++) {
System.out.println("我是C线程");
}
//C线程打印完毕,标识位置为1,唤醒A种类的线程
this.flag = 1;
condition1.signalAll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
/**
*
* @ClassName: LockDemo2
* @Description: 启动类,测试闭环调用
* @author: fuling
* @date: 2020年9月10日 下午12:51:06
*/
public class LockDemo2 {
public static void main(String[] args) {
Printer printer = new Printer();//获取打印机资源类
//创建A,B,C线程各10个
for(int i = 0; i < 10; i++) {
new Thread(()->{
printer.printA();
}).start();;
}
for(int i = 0; i < 10; i++) {
new Thread(()->{
printer.printB();
}).start();;
}
for(int i = 0; i < 10; i++) {
new Thread(()->{
printer.printC();
}).start();;
}
}
}
执行结果
我是A线程
我是A线程
我是A线程
我是A线程
我是A线程
我是B线程
我是B线程
我是B线程
我是B线程
我是B线程
我是B线程
我是B线程
我是B线程
我是B线程
我是B线程
我是C线程
我是C线程
我是C线程
我是C线程
我是C线程
我是C线程
我是C线程
我是C线程
我是C线程
我是C线程
我是C线程
我是C线程
我是C线程
我是C线程
我是C线程
我是A线程
我是A线程
我是A线程
我是A线程
我是A线程
…