JUC源码简析 CyclicBarrier

相关阅读

简介

CyclicBarrier表示可循环使用栅栏,即一个可循环利用的屏障,可以让所有线程彼此等待,直到所有线程都完成相应任务后,然后屏障前的所有线程才继续下一步动作;
内部持有的ReentrantLock的实例,保护屏障的入口;持有的Condition的实例,充当屏障;

和CountDownLatch的比较

  1. CountDownLatch是线程组之间的等待,即一个(或多个)线程等待其它N个线程完成相应任务后再执行下一步;而CyclicBarrier是线程组内的等待,即组内的每个线程相互等待,等都到达屏障,再执行下一步;
  2. CountDownLatch计数为0时无法重置,即无法循环使用;而CyclicBarrier计数达到初始值时,可以重置,即可以循环使用;

源码简析

内部类——Generation

private static class Generation {
    boolean broken = false;
}

维护等待线程的状态;

CyclicBarrier

构造方法

public CyclicBarrier(int parties, Runnable barrierAction) {
    // parties表示线程组中线程的个数,即要推倒栅栏(执行await方法)的线程个数,必须大于0
    if (parties <= 0) throw new IllegalArgumentException();
    this.parties = parties;
    this.count = parties;
    // 栅栏推倒后需要执行的任务,可以为null
    this.barrierCommand = barrierAction;
}

public CyclicBarrier(int parties) {
    this(parties, null);
}

nextGeneration

private void nextGeneration() {
    // 调用Condition的signalALL方法,唤醒所有等待线程
    trip.signalAll();
    // 重设count为parties
    count = parties;
    // 重设generation成员
    generation = new Generation();
}

本方法只能在持有锁的时候调用;

breakBarrier

private void breakBarrier() {
    // 设置generation状态为“推倒”
    generation.broken = true;
    // 重设count为parties
    count = parties;
    // 调用Condition的signalALL方法,唤醒所有等待线程
    trip.signalAll();
}

本方法只能在持有锁的时候调用;

dowait

private int dowait(boolean timed, long nanos)
    throws InterruptedException, BrokenBarrierException, TimeoutException {
    final ReentrantLock lock = this.lock;
    // 先上锁
    lock.lock();
    try {
        final Generation g = generation;
        if (g.broken)
            // 此时栅栏状态已经是“推倒”,则抛出BrokenBarrierException
            throw new BrokenBarrierException();

        // 如果当前线程发生过中断
        if (Thread.interrupted()) {
            // 调用breakBarrier推倒栅栏
            breakBarrier();
            // 抛出InterruptedException
            throw new InterruptedException();
        }

        int index = --count;
        // 如果栅栏的等待线程数量为0,说明最后一个线程达到栅栏,可以推倒栅栏了
        if (index == 0) {
            boolean ranAction = false;
            try {
                final Runnable command = barrierCommand;
                if (command != null)
                    // 推倒栅栏前有任务执行,则执行该任务
                    command.run();
                // 设置推倒栅栏成功标志为true
                ranAction = true;
                // 开启下一循环,可循环使用的体现
                nextGeneration();
                return 0;
            } finally {
                // 当执行推倒栅栏后的任务发生异常时进入
                if (!ranAction)
                    // 若还未推倒栅栏,则推倒栅栏
                    breakBarrier();
            }
        }

        // 死循环执行,确保本线程挂住,除非栅栏被推倒,或者本线程发生中断或者超时
        for (;;) {
            try {
                if (!timed)
                    // 不关心超时,则调用Condition.await释放锁资源,进行等待状态
                    trip.await();
                else if (nanos > 0L)
                    // 若关心超时,且超时时间大于0,则调用Condition.awaitNanos释放锁资源,同时设置了超时时间,进行等待状态等待
                    nanos = trip.awaitNanos(nanos);
            } catch (InterruptedException ie) {
                // 本线程在等待过程中发生中断异常

                // 如果当前栅栏信息没变化且栅栏还没被推倒
                if (g == generation && ! g.broken) {
                    // 推倒栅栏,因为等待发生中断,栅栏就失效了
                    breakBarrier();
                    // 继续抛出InterruptedException
                    throw ie;
                } else {
                    // 虽然本线程发生了中断,但栅栏信息已经变化
                    //     1. 变成新栅栏,本线程不属于新栅栏,不会对新栅栏有影响
                    //     2. 栅栏已被推倒,那么即使本线程未发生中断,也会被其它线程推倒栅栏时唤醒
                    // 所以此中断没啥作用,只需要重新设置中断标志即可
                    Thread.currentThread().interrupt();
                }
            }

            // 1. 可能是被其它推倒栅栏的线程调用signalAll唤醒;
            // 2. 可能是本线程发生中断异常唤醒;
            // 3. 可能是本线程设置超时时间,超时导致唤醒;
            // 4. 可能是本线程设置超时时间不大于0

            if (g.broken)
                // 如果记录的栅栏为“推倒”状态,则抛出BrokenBarrierException
                throw new BrokenBarrierException();

            if (g != generation)
                // 如果栅栏信息变化,则表示因为其它线程执行换代操作而唤醒本线程
                // 则直接返回原先记录的栅栏的等待线程数量(当前线程所在栅栏的下标)
                return index;

            if (timed && nanos <= 0L) {
                // 线程关心超时且发生了超时,则栅栏失效了
                
                // 推倒栅栏
                breakBarrier();
                // 抛出TimeoutException
                throw new TimeoutException();
            }
        }
    } finally {
        // finally代码块确保lock被释放
        lock.unlock();
    }
}

await

public int await() throws InterruptedException, BrokenBarrierException {
    try {
        return dowait(false, 0L);
    } catch (TimeoutException toe) {
        // 未设置超时时间却发生超时异常,则抛出错误
        throw new Error(toe);
    }
}

public int await(long timeout, TimeUnit unit)
    throws InterruptedException,
           BrokenBarrierException,
           TimeoutException {
    return dowait(true, unit.toNanos(timeout));
}

isBroken

public boolean isBroken() {
    final ReentrantLock lock = this.lock;
    // 先上锁
    lock.lock();
    try {
        // 返回当前栅栏的状态
        return generation.broken;
    } finally {
        // finally代码块确保lock被释放
        lock.unlock();
    }
}

reset

public void reset() {
    final ReentrantLock lock = this.lock;
    // 先上锁
    lock.lock();
    try {
        // 推倒栅栏
        breakBarrier();
        // 开启新的栅栏
        nextGeneration();
    } finally {
        // finally代码块确保lock被释放
        lock.unlock();
    }
}

getNumberWaiting

public int getNumberWaiting() {
    final ReentrantLock lock = this.lock;
    // 先上锁
    lock.lock();
    try {
        return parties - count;
    } finally {
        // finally代码块确保lock被释放
        lock.unlock();
    }
}

测试

Demo

class Demo {
    private int parties = 5;
    private CyclicBarrier cyclicBarrier = new CyclicBarrier(5, new Runnable() {
        @Override
        public void run() {
            System.out.println("推倒栅栏");
        }
    });


    public static void main(String[] args) throws InterruptedException {
        Demo demo = new Demo();
        ExecutorService es = Executors.newFixedThreadPool(demo.parties);

        for (int i=0; i<demo.parties; i++) {
            es.execute(new CyclicBarrierTask(demo.cyclicBarrier));
        }

        es.shutdown();
    }


    private static class CyclicBarrierTask implements Runnable {

        private CyclicBarrier cb;


        CyclicBarrierTask(CyclicBarrier cb) {
            this.cb = cb;
        }

        @Override
        public void run() {
            int threadIndex = 0;
            try {
                TimeUnit.SECONDS.sleep(2);
                System.out.println(Thread.currentThread().getName() + " arrive to barrier at first time");
                threadIndex = cb.await();
                System.out.println(Thread.currentThread().getName() + " at index " + (cb.getParties()-threadIndex) + " of the barrier breaks barrier at first time");

                TimeUnit.SECONDS.sleep(2);

                System.out.println(Thread.currentThread().getName() + " arrive to barrier at twice time");
                threadIndex = cb.await();
                System.out.println(Thread.currentThread().getName() + " at index " + (cb.getParties()-threadIndex) + " of the barrier breaks barrier at twice time");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
}

测试结果

pool-1-thread-2 arrive to barrier at first time
pool-1-thread-1 arrive to barrier at first time
pool-1-thread-4 arrive to barrier at first time
pool-1-thread-3 arrive to barrier at first time
pool-1-thread-5 arrive to barrier at first time
推倒栅栏
pool-1-thread-5 at index 5 of the barrier breaks barrier at first time
pool-1-thread-3 at index 4 of the barrier breaks barrier at first time
pool-1-thread-4 at index 3 of the barrier breaks barrier at first time
pool-1-thread-1 at index 2 of the barrier breaks barrier at first time
pool-1-thread-2 at index 1 of the barrier breaks barrier at first time
pool-1-thread-1 arrive to barrier at twice time
pool-1-thread-4 arrive to barrier at twice time
pool-1-thread-5 arrive to barrier at twice time
pool-1-thread-3 arrive to barrier at twice time
pool-1-thread-2 arrive to barrier at twice time
推倒栅栏
pool-1-thread-2 at index 5 of the barrier breaks barrier at twice time
pool-1-thread-4 at index 2 of the barrier breaks barrier at twice time
pool-1-thread-1 at index 1 of the barrier breaks barrier at twice time
pool-1-thread-5 at index 3 of the barrier breaks barrier at twice time
pool-1-thread-3 at index 4 of the barrier breaks barrier at twice time
【电力系统】单机无穷大电力系统短路故障暂态稳定Simulink仿真(带说明文档)内容概要:本文档围绕“单机无穷大电力系统短路故障暂态稳定Simulink仿真”展开,提供了完整的仿真模型与说明文档,重点研究电力系统在发生短路故障后的暂态稳定性问题。通过Simulink搭建单机无穷大系统模型,模拟不同类型的短路故障(如三相短路),分析系统在故障期间及切除后的动态响应,包括发电机转子角度、转速、电压和功率等关键参数的变化,进而评估系统的暂态稳定能力。该仿真有助于理解电力系统稳定性机理,掌握暂态过程分析方法。; 适合人群:电气工程及相关专业的本科生、研究生,以及从事电力系统分析、运行与控制工作的科研人员和工程师。; 使用场景及目标:①学习电力系统暂态稳定的基本概念与分析方法;②掌握利用Simulink进行电力系统建模与仿真的技能;③研究短路故障对系统稳定性的影响及提高稳定性的措施(如故障清除时间优化);④辅助课程设计、毕业设计或科研项目中的系统仿真验证。; 阅读建议:建议结合电力系统稳定性理论知识进行学习,先理解仿真模型各模块的功能与参数设置,再运行仿真并仔细分析输出结果,尝试改变故障类型或系统参数以观察其对稳定性的影响,从而深化对暂态稳定问题的理解。
本研究聚焦于运用MATLAB平台,将支持向量机(SVM)应用于数据预测任务,并引入粒子群优化(PSO)算法对模型的关键参数进行自动调优。该研究属于机器学习领域的典型实践,其核心在于利用SVM构建分类模型,同时借助PSO的全局搜索能力,高效确定SVM的最优超参数配置,从而显著增强模型的整体预测效能。 支持向量机作为一种经典的监督学习方法,其基本原理是通过在高维特征空间中构造一个具有最大间隔的决策边界,以实现对样本数据的分类或回归分析。该算法擅长处理小规模样本集、非线性关系以及高维度特征识别问题,其有效性源于通过核函数将原始数据映射至更高维的空间,使得原本复杂的分类问题变得线性可分。 粒子群优化算法是一种模拟鸟群社会行为的群体智能优化技术。在该算法框架下,每个潜在解被视作一个“粒子”,粒子群在解空间中协同搜索,通过不断迭代更新自身速度与位置,并参考个体历史最优解和群体全局最优解的信息,逐步逼近问题的最优解。在本应用中,PSO被专门用于搜寻SVM中影响模型性能的两个关键参数——正则化参数C与核函数参数γ的最优组合。 项目所提供的实现代码涵盖了从数据加载、预处理(如标准化处理)、基础SVM模型构建到PSO优化流程的完整步骤。优化过程会针对不同的核函数(例如线性核、多项式核及径向基函数核等)进行参数寻优,并系统评估优化前后模型性能的差异。性能对比通常基于准确率、精确率、召回率及F1分数等多项分类指标展开,从而定量验证PSO算法在提升SVM模型分类能力方面的实际效果。 本研究通过一个具体的MATLAB实现案例,旨在演示如何将全局优化算法与机器学习模型相结合,以解决模型参数选择这一关键问题。通过此实践,研究者不仅能够深入理解SVM的工作原理,还能掌握利用智能优化技术提升模型泛化性能的有效方法,这对于机器学习在实际问题中的应用具有重要的参考价值。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值