同步工具类使用–顺序循环打印ABC
同步工具类基础概念点击这里
1.synchronized
/**
* 使用synchronized实现
* 具体思路:
* 1.线程t1唤醒t2,t2唤醒t3,t3唤醒t1;
* 2.由于在唤醒过程中不能唤醒指定线程,所以
* 2.1 使用notifyAll()方法唤醒所有的线程,然后多个线程去竞争锁;
* 2.2 判断条件处使用while循环,当条件成立时,当前线程一直处于wait状态。
*/
static class Worker{
private volatile int num = 1;
public void loopA(String str){
synchronized (this){
while(num != 1){
try {
this.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println(str);
num = 2;
this.notifyAll();
}
}
public void loopB(String str){
synchronized (this){
while(num != 2){
try {
this.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println(str);
num = 3;
this.notifyAll();
}
}
public void loopC(String str){
synchronized (this){
while(num != 3){
try {
this.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println(str);
num = 1;
this.notifyAll();
}
}
}
static class ThreadABC implements Runnable{
private Worker work;
private String str;
public ThreadABC(Worker work, String str){
this.work = work;
this.str = str;
}
@Override
public void run() {
for(int i=0;i<10;i++){
if("A".equals(str)){
work.loopA(str);
}else if("B".equals(str)){
work.loopB(str);
}else if("C".equals(str)){
work.loopC(str);
}
}
}
}
public static void main(String[] args) {
Worker w = new Worker();
Thread t1 = new Thread(new ThreadABC(w, "A"));
Thread t2 = new Thread(new ThreadABC(w, "B"));
Thread t3 = new Thread(new ThreadABC(w, "C"));
t1.start();
t2.start();
t3.start();
}
2.ReentrantLock + Condition
/**
* 使用ReentrantLock + Condition实现
* 具体思路:
* 1.三个条件队列,t1唤醒t2,t2唤醒t3,t3唤醒t1;
* 2.Condition可以指定需要唤醒的线程。
*/
static class Worker{
private Lock lock = new ReentrantLock();
private Condition c1 = lock.newCondition();
private Condition c2 = lock.newCondition();
private Condition c3 = lock.newCondition();
private volatile int num = 1;
public void loopA(String str){
lock.lock();
try{
if(num != 1){
c1.await();
}
System.out.println(str);
num = 2;
c2.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void loopB(String str){
lock.lock();
try{
if(num != 2){
c2.await();
}
System.out.println(str);
num = 3;
c3.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void loopC(String str){
lock.lock();
try{
if(num != 3){
c3.await();
}
System.out.println(str);
num = 1;
c1.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
3.CyclicBarrier
/**
* 使用CyclicBarrier实现,CyclicBarrier内部为ReentrantLock + Condition
* 具体思路:
* 1.使用三个栅栏,cb1和cb2需要等待两个线程,cb3需要等待3个线程;
* 2.打印A的时候cb1,cb3等待;
* 3.cb1等待,由于cb1需要等待两个线程,此时线程t1,t2都到了栅栏位置,可以执行下面的代码,打印B,并且cb2,cb3等待;
* 4.cb2等待,由于cb2需要等待两个线程,此时线程t2,t3都到了栅栏位置,可以执行下面的代码,打印C,并且cb3等待;
* 5.cb3等待了3次,此时t1,t2,t3都到了栅栏位置,打印A,进入下一个周期。
*/
static class Worker{
CyclicBarrier cb1 = new CyclicBarrier(2);
CyclicBarrier cb2 = new CyclicBarrier(2);
CyclicBarrier cb3 = new CyclicBarrier(3);
public void loopA(String str){
try {
System.out.println(str);
cb1.await();
cb3.await();
} catch (Exception e) {
e.printStackTrace();
}
}
public void loopB(String str){
try {
cb1.await();
System.out.println(str);
cb2.await();
cb3.await();
} catch (Exception e) {
e.printStackTrace();
}
}
public void loopC(String str){
try {
cb2.await();
System.out.println(str);
cb3.await();
} catch (Exception e) {
e.printStackTrace();
}
}
}
4.Phaser
/**
* 使用Phaser(移相器/阶段器)实现,Semaphore内部为AQS共享锁的实现
* 具体思路:
* 和CyclicBarrier类似
*/
static class Worker{
Phaser p1 = new Phaser(2);
Phaser p2 = new Phaser(2);
Phaser p3 = new Phaser(3);
public void loopA(String str){
System.out.println(str);
p1.arriveAndAwaitAdvance();
p3.arriveAndAwaitAdvance();
}
public void loopB(String str){
p1.arriveAndAwaitAdvance();
System.out.println(str);
p2.arriveAndAwaitAdvance();
p3.arriveAndAwaitAdvance();
}
public void loopC(String str){
p2.arriveAndAwaitAdvance();
System.out.println(str);
p3.arriveAndAwaitAdvance();
}
}
5.Semaphore
/**
* 使用Semaphore实现,Semaphore内部为AQS共享锁的实现
* 具体思路:
* 1.三个信号量对象,初始只有sp1有一个permits(许可);
* 2.permits是指允许有多少个线程同步执行;
* 3.permits值不能小于0,当等于0时,acquire()方法被阻塞,等待其他线程调用release()方法;
* 4.当调用acquire()方法时阻塞,直到有一个许可可以获得,然后拿走一个许可,进行后面的逻辑;
* 5.当调用release()方法时增加一个许可。
*/
static class Worker{
private Semaphore sp1 = new Semaphore(1);
private Semaphore sp2 = new Semaphore(0);
private Semaphore sp3 = new Semaphore(0);
public void loopA(String str){
try {
sp1.acquire();
System.out.println(str);
sp2.release();
} catch (Exception e) {
e.printStackTrace();
}
}
public void loopB(String str){
try {
sp2.acquire();
System.out.println(str);
sp3.release();
} catch (Exception e) {
e.printStackTrace();
}
}
public void loopC(String str){
try {
sp3.acquire();
System.out.println(str);
sp1.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}