juc包下CyclicBarrier

CyclicBarrier概念

这个是在并发时,要求所有线程都到达屏障,最后统一释放

那他有啥作用那也就是

让一组线程相互等待,等待所有的线程都到达公共屏障点

这个屏障点Barrier

CyclicBarrier类中的方法和参数

 参数详解

public class CyclicBarrier { 

   
    /** The lock for guarding barrier entry */
    //lock锁,针对于屏障来服务
    private final ReentrantLock lock = new ReentrantLock();
    /** Condition to wait on until tripped */
    // 用于声明等待的队列
    private final Condition trip = lock.newCondition();
    /** The number of parties */
    //线程数量
    private final int parties;
    /* The command to run when tripped */
    // 所有线程到达后,最后一个线程要做的事情
    private final Runnable barrierCommand;
    /** The current generation */
    //当前代,每次循环都是一代
    private Generation generation = new Generation();

    /**
     * Number of parties still waiting. Counts down from parties to 0
     * on each generation.  It is reset to parties on each new
     * generation or when broken.
     */
    //等待的线程数量
    private int count;

    ...

}

CyclicBarrier的构造函数

/**
     * Creates a new {@code CyclicBarrier} that will trip when the
     * given number of parties (threads) are waiting upon it, and which
     * will execute the given barrier action when the barrier is tripped,
     * performed by the last thread entering the barrier.
     *
     * @param parties the number of threads that must invoke {@link #await}
     *        before the barrier is tripped
     * @param barrierAction the command to execute when the barrier is
     *        tripped, or {@code null} if there is no action
     * @throws IllegalArgumentException if {@code parties} is less than 1
     *  声明有多少个线程执行,和线程到达后,最后一个线程干什么
     */
    public CyclicBarrier(int parties, Runnable barrierAction) {
        if (parties <= 0) throw new IllegalArgumentException();
        this.parties = parties;
        this.count = parties;
        this.barrierCommand = barrierAction;
    }

    /**
     * Creates a new {@code CyclicBarrier} that will trip when the
     * given number of parties (threads) are waiting upon it, and
     * does not perform a predefined action when the barrier is tripped.
     *
     * @param parties the number of threads that must invoke {@link #await}
     *        before the barrier is tripped
     * @throws IllegalArgumentException if {@code parties} is less than 1
     *  只声明有多少个线程执行,执行后,什么也不干
     */
    public CyclicBarrier(int parties) {
        this(parties, null);
    }

CyclicBarrier等待执行

让parties个线程等待执行

直到parties个线程到达barrier” 或 “当前线程被中断” 或 “超时”这3者之一发生,当前线程就会继续执行

/**
     * Waits until all {@linkplain #getParties parties} have invoked
     * {@code await} on this barrier.
     *
     * <p>If the current thread is not the last to arrive then it is
     * disabled for thread scheduling purposes and lies dormant until
     * one of the following things happens:
     * <ul>
     * <li>The last thread arrives; or
     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
     * the current thread; or
     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
     * one of the other waiting threads; or
     * <li>Some other thread times out while waiting for barrier; or
     * <li>Some other thread invokes {@link #reset} on this barrier.
     * </ul>
     *
     * <p>If the current thread:
     * <ul>
     * <li>has its interrupted status set on entry to this method; or
     * <li>is {@linkplain Thread#interrupt interrupted} while waiting
     * </ul>
     * then {@link InterruptedException} is thrown and the current thread's
     * interrupted status is cleared.
     *
     * <p>If the barrier is {@link #reset} while any thread is waiting,
     * or if the barrier {@linkplain #isBroken is broken} when
     * {@code await} is invoked, or while any thread is waiting, then
     * {@link BrokenBarrierException} is thrown.
     *
     * <p>If any thread is {@linkplain Thread#interrupt interrupted} while waiting,
     * then all other waiting threads will throw
     * {@link BrokenBarrierException} and the barrier is placed in the broken
     * state.
     *
     * <p>If the current thread is the last thread to arrive, and a
     * non-null barrier action was supplied in the constructor, then the
     * current thread runs the action before allowing the other threads to
     * continue.
     * If an exception occurs during the barrier action then that exception
     * will be propagated in the current thread and the barrier is placed in
     * the broken state.
     *
     * @return the arrival index of the current thread, where index
     *         {@code getParties() - 1} indicates the first
     *         to arrive and zero indicates the last to arrive
     * @throws InterruptedException if the current thread was interrupted
     *         while waiting
     * @throws BrokenBarrierException if <em>another</em> thread was
     *         interrupted or timed out while the current thread was
     *         waiting, or the barrier was reset, or the barrier was
     *         broken when {@code await} was called, or the barrier
     *         action (if present) failed due to an exception
     */
    public int await() throws InterruptedException, BrokenBarrierException {
        try {
            return dowait(false, 0L);
        } catch (TimeoutException toe) {
            throw new Error(toe); // cannot happen
        }
    }

首先调用dowait()方法,这个方法在源码中页写到是barrier的核心方法

这个方法声明了一个可重入锁,通过这个锁来实现Barrier

/**
     * Main barrier code, covering the various policies.
     */
    private int dowait(boolean timed, long nanos)
        throws InterruptedException, BrokenBarrierException,
               TimeoutException {
        final ReentrantLock lock = this.lock;
        // 首先获取这个独占锁
        lock.lock();
        try {
            // 保存当前的generation
            final Generation g = generation;
            //如果broken为true,则代表这个栅栏已经被损坏,抛出异常
            if (g.broken)
                throw new BrokenBarrierException();
            //判断是否线程中断,如果中断,则利用breakBarrier方法打破栅栏,
            // 让所有等待的线程执行
            if (Thread.interrupted()) {
                breakBarrier();
                throw new InterruptedException();
            }
            //将技术减一
            int index = --count;
            //判断是否已经有parties个线程到达屏障
            if (index == 0) {  // tripped
                boolean ranAction = false;
                try {
                    final Runnable command = barrierCommand;
                    //判断是否有线程到达后要做的事情,如果有,就立刻执行
                    if (command != null)
                        command.run();
                    ranAction = true;
                    //唤醒所有线程,更新下一代
                    nextGeneration();
                    return 0;
                } finally {
                    if (!ranAction)
                        breakBarrier();
                }
            }
            // 当前线程一直阻塞,直到“有parties个线程到达barrier” 或 “当前线程被中断” 或             
            //  “超时”这3者之一发生,
            // loop until tripped, broken, interrupted, or timed out
            for (;;) {
                try {
                   // 判断是否是超时等待,如果不是,就调用awaitNanos(nanos)
                    if (!timed)
                        trip.await();
                    else if (nanos > 0L)
                        nanos = trip.awaitNanos(nanos);
                } catch (InterruptedException ie) {
                    // 判断线程在执行过程中,这个栅栏是否被破坏
                    if (g == generation && ! g.broken) {
                        breakBarrier();
                        throw ie;
                    } else {
                        // We're about to finish waiting even if we had not
                        // been interrupted, so this interrupt is deemed to
                        // "belong" to subsequent execution.
                        Thread.currentThread().interrupt();
                    }
                }
                // 栅栏破坏,抛出异常
                if (g.broken)
                    throw new BrokenBarrierException();
                // 判断是否开启下一代,是的话,返回index值
                if (g != generation)
                    return index;
                //如果时间等待超时,则打破栅栏,调用breakBarrier()方法,让所有线程一起执行
                //并且抛出一个超时异常
                if (timed && nanos <= 0L) {
                    breakBarrier();
                    throw new TimeoutException();
                }
            }
        } finally {
            //释放这把可重入锁
            lock.unlock();
        }
    }

好像Generation没有具体细说

Generation是CyclicBarrier的一代线程,这是为了CyclicBarrier可以重复使用

/**
     * Each use of the barrier is represented as a generation instance.
     * The generation changes whenever the barrier is tripped, or
     * is reset. There can be many generations associated with threads
     * using the barrier - due to the non-deterministic way the lock
     * may be allocated to waiting threads - but only one of these
     * can be active at a time (the one to which {@code count} applies)
     * and all the rest are either broken or tripped.
     * There need not be an active generation if there has been a break
     * but no subsequent reset.
     */
    private static class Generation {
        boolean broken = false;
    }

再说一下CyclicBarrier的方法reset()的方法

重新获得这把可重入锁,打破栅栏,开启下一代,重置count

/**
     * Resets the barrier to its initial state.  If any parties are
     * currently waiting at the barrier, they will return with a
     * {@link BrokenBarrierException}. Note that resets <em>after</em>
     * a breakage has occurred for other reasons can be complicated to
     * carry out; threads need to re-synchronize in some other way,
     * and choose one to perform the reset.  It may be preferable to
     * instead create a new barrier for subsequent use.
     */
    public void reset() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            breakBarrier();   // break the current generation
            nextGeneration(); // start a new generation
        } finally {
            lock.unlock();
        }
    }

多多练习


public static void main(String[] args){
CyclicBarrier barrier=new CyclicBarrier(2);
		
		for(int i=0;i<2;i++){
			Thread thread1=new Thread(new Runnable(){

				@Override
				public void run() {
					// TODO 自动生成的方法存根
					try {
						System.out.println("我是"+Thread.currentThread().getName()+
"线程");
						
						barrier.await();
						System.out.println("我在阻塞完之后执行...");
					} catch (InterruptedException e) {
						// TODO 自动生成的 catch 块
						e.printStackTrace();
					} catch (BrokenBarrierException e) {
						// TODO 自动生成的 catch 块
						e.printStackTrace();
					}
				}
				
			});
			thread1.start();
		}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

羊驼有点累

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值