版权声明:作者: 阿顾, 转载请写明出处, 谢谢 https://blog.csdn.net/u010452388/article/details/82777908
先上效果图:
目录
资源
这里用了condition
执行流程:线程1执行完,让线程2醒来工作;线程2执行完,让线程3醒来工作;线程3执行完,让线程1醒来工作
原理(都是按最坏的情况分析):
①一开始3个线程抢锁,如果线程2和3抢到锁,会进入等待(因为num=1),并释放锁,此时只有线程1可以拿锁
②线程1开始执行,将num=2,并唤醒线程2,此时线程1和线程2竞争锁,如果线程1抢到锁,会进入等待,并释放锁,此时只有线程2可以拿锁
③线程2开始执行,将num=3,并唤醒线程3,此时线程2和线程3竞争锁,如果线程2抢到锁,会进入等待,并释放锁,此时只有线程3可以拿锁
④线程3开始执行,将num=1,并唤醒线程1,此时线程3和线程1竞争锁,如果线程3抢到锁,会进入等待,并释放锁,此时只有线程1可以拿锁
这样就能保证三个线程循环执行了
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Resource {
//num=1就是线程1执行,num=2就是线程2执行,num=3就是线程3执行
private int num = 1;
private Lock lock = new ReentrantLock();//创建锁对象
private Condition condition1 = lock.newCondition();//条件1
private Condition condition2 = lock.newCondition();//条件2
private Condition condition3 = lock.newCondition();//条件3
public void sub1() {
try {
lock.lock();//开启锁
while (num != 1){//这里jdk源码里推荐用while,因为有可能出现虚假唤醒,所以要再次确认
try {
condition1.await();//条件1线程等待,并释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//运行到这里,说明num=1
num=2;
Thread.sleep(1000);
System.out.println("线程1运行完毕");
condition2.signal();//唤醒条件2线程
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();//释放锁
}
}
public void sub2() {
try {
lock.lock();//开启锁
while (num !=2) {//这里jdk源码里推荐用while,因为有可能出现虚假唤醒,所以要再次确认
try {
condition2.await();//条件2线程等待,并释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果线程执行到这里,说明num=2
num=3;
Thread.sleep(1000);
System.out.println("线程2运行完毕");
condition3.signal();//唤醒条件3线程
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();//释放锁
}
}
public void sub3() {
try {
lock.lock();//开启锁
while (num !=3) {//这里jdk源码里推荐用while,因为有可能出现虚假唤醒,所以要再次确认
try {
condition3.await();//条件3线程等待,并释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果线程执行到这里,说明num=3
num=1;
Thread.sleep(1000);
System.out.println("线程3运行完毕");
condition1.signal();//唤醒条件1线程
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();//释放锁
}
}
}
测试
public static void main(String[] args) {
Resource resource = new Resource();
//第一个线程
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
resource.sub1();
}
}
}).start();
//第二个线程
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
resource.sub2();
}
}
}).start();
//第三个线程
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
resource.sub3();
}
}
}).start();
}