java高并发、多线程(九)-- CyclicBarrier

java高并发、多线程(九)

CyclicBarrier

代码事例

先看一段代码:

public class CyclicBarrierTest {

  	public static void main(String[] args) {
        CyclicBarrier cb = new CyclicBarrier(2,() -> System.out.println(Thread.currentThread().getName() + "执行CyclicBarrier逻辑"));

        for (int i = 0; i < 4; i++) {
            new Thread(()->{
                try {
                    System.out.println(Thread.currentThread().getName() + "start");
                    cb.await();
                    System.out.println(Thread.currentThread().getName() + "end");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            },"Thread-" + i).start();
        }
    }
}

运行结果:
在这里插入图片描述
功能:CyclicBarrier 会阻塞指定数量线程后运行已定义的Runnable接口,再唤醒阻塞线程继续执行。

源码结构

public class CyclicBarrier {
    
    private static class Generation {
        boolean broken = false;
    }

    //ReentrantLock锁
    private final ReentrantLock lock = new ReentrantLock();
    //等待触发条件
    private final Condition trip = lock.newCondition();
    //每部分的数量
    private final int parties;
    //触发后需要运行的逻辑
    private final Runnable barrierCommand;
    private Generation generation = new Generation();

    //还需要等待多少数量
    private int count;
	
	//构造方法
	public CyclicBarrier(int parties, Runnable barrierAction) {
        if (parties <= 0) throw new IllegalArgumentException();
        this.parties = parties;
        this.count = parties;
        this.barrierCommand = barrierAction;
    }
    public CyclicBarrier(int parties) {
        this(parties, null);
    }
}

事例执行流程

CyclicBarrier cb = new CyclicBarrier(2,() -> System.out.println(Thread.currentThread().getName() + "执行CyclicBarrier逻辑"));

首先jvm将加载CyclicBarrier类,然后再创建对象调用构造方法赋初始值。此时parties 、count 值为2,barrierCommand 为实现Runnable接口(System.out.println(Thread.currentThread().getName() + “执行CyclicBarrier逻辑”))的对象。
紧接着for循环陆续创建4个线程并启动。

  • Thread-0(阻塞线程流程)
    1、控制台打印Thread-0 start。
    2、调用await()方法。
		public int await() throws InterruptedException, BrokenBarrierException {
        try {
        //返回dowait()
            return dowait(false, 0L);
        } catch (TimeoutException toe) {
            throw new Error(toe); // cannot happen
        }
    }

继续查看dowait(false, 0L)方法

	private int dowait(boolean timed, long nanos)
        throws InterruptedException, BrokenBarrierException,
               TimeoutException {
        final ReentrantLock lock = this.lock;
        //加锁
        lock.lock();
        try {
        	/*此处代码省略...*/
			//count初始为2
            int index = --count;
            if (index == 0) {  // tripped
               /*此处代码省略...*/
            }
            for (;;) {
                try {
                	//time : false
                    if (!timed)
                    	//条件等待
                        trip.await();
                    else if (nanos > 0L)
                        nanos = trip.awaitNanos(nanos);
                } catch (InterruptedException ie) {
                    /*此处代码省略...*/
                }
                 /*此处代码省略...*/
            }
        } finally {
            lock.unlock();
        }
    }
}

继续查看trip.await(); ConditionObject类中方法:

public final void await() throws InterruptedException {
    if (Thread.interrupted())
        throw new InterruptedException();
    //将此线程添加到条件等待队列中
    Node node = addConditionWaiter();
    //释放锁,调用dowait方法时,加了ReentrantLock 锁
    int savedState = fullyRelease(node);
    int interruptMode = 0;
    while (!isOnSyncQueue(node)) {
    	//阻塞当前线程Thread-0,前面有一个释放锁的操作,同样也证明了LockSupport.park不会释放锁
        LockSupport.park(this);
        /*此处代码省略...*/
}
  • Thread-2(达到条件线程流程)

开始流程与Thread-0一致,在dowait(false, 0L)方法中执行了不同分支逻辑

	private int dowait(boolean timed, long nanos)
        throws InterruptedException, BrokenBarrierException,
               TimeoutException {
        final ReentrantLock lock = this.lock;
        //加锁
        lock.lock();
        try {
            /*此处代码省略...*/
			//经过Thread-0线程执行后,count值为1
            int index = --count;
            if (index == 0) {  // tripped
                boolean ranAction = false;
                try {
                    final Runnable command = barrierCommand;
                    if (command != null)
                    	//执行 System.out.println(Thread.currentThread().getName() + "执行CyclicBarrier逻辑")
                        command.run();
                    ranAction = true;
                    //更新状态并唤醒阻塞的线程
                    nextGeneration();
                    return 0;
                } finally {
                    if (!ranAction)
                        breakBarrier();
                }
            }
            /*此处代码省略...*/
        } finally {
            lock.unlock();
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值