zoukankan      html  css  js  c++  java
  • 高并发和多线程(三)——CountDownLatch,CyclicBarrier,Phaser,ReadWriteLock,Exchanger,LockSupport

    写一下多线程下面经常用的方法,理解用好这些方法,能解决很多问题

    CountDownLatch


    private static void useContDownLatch(){
    Thread[] t1 = new Thread[100];
    CountDownLatch countdown = new CountDownLatch(t1.length);

    for (int i = 0; i <t1.length ; i++) {
    new Thread(()->{
    System.out.println(Thread.currentThread().getName()+"-开始计算");
    try {
    TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName()+"-计算完成");
    countdown.countDown();
    }).start();

    }

    try {
    countdown.await();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println("countdown end ----");
    }

    第一个是开始信号,在发出执行命令前,阻止线程开始执行。

    第二个是完成信号,直到所有线程执行完毕,主线程再开始执行。

    使用场景:

    CountDownLatch 就是一个信号器,在多线程情况下每次执行contdown()方法就会减1,一直减到0为止,我在实际使用场景中是在多表刷数据工具,使用时启用一个线程池,声明一个count为2000的信号器,一个线程跑完一张表countdown一次,循环跑完2000张表然后await,
    数据清洗完毕更新记录表,记录表中间如果有异常会记录在哪张表出的异常,可以下次直接从记录表拿到当前表开始清洗数据。

    CyclicBarrier


    private static void useCyclicBarrier(){

    CyclicBarrier cyclicBarrier = new CyclicBarrier(5, new Runnable() {
    @Override
    public void run() {

    System.out.println("满人,我们开始干掉他们");
    }
    });

    for (int i = 0; i <100 ; i++) {
    new Thread(()->{
    try {
    System.out.println("我来加入王者战队了");
    cyclicBarrier.await();
    } catch (InterruptedException e) {
    e.printStackTrace();
    } catch (BrokenBarrierException e) {
    e.printStackTrace();
    }
    }).start();
    }
    }


    多个线程互相等待,直到到达同一个同步点,再继续一起执行。CyclicBarrier适用于多个线程有固定的多步需要执行,线程间互相等待,当都执行完了,在一起执行下一步。
    以上的例子利用了CyclicBarrier提供的一个更高级的构造函数CyclicBarrier(int parties, Runnable barrierAction),用于在线程到达屏障时,优先执行barrierAction,方便处理更复杂的业务场景。
    使用场景
    假设要进行一个大量的计算,得到最终的值。如果使用单线程会很慢,使用多线程,又不知道最终什么时候把结果合并,这个使用 CyclicBarrier 就很有用了

    Phaser

    private static void userPhaser(){
    MarriagePhaser phaser = new MarriagePhaser();
    phaser.bulkRegister(5);
    for (int i = 0; i <5 ; i++) {
    final int nameIndex = i;
    new Thread(()->{
    Person p = new Person("person"+nameIndex);
    p.arrive();
    phaser.arriveAndAwaitAdvance();

    p.eat();
    phaser.arriveAndAwaitAdvance();

    p.leave();
    phaser.arriveAndAwaitAdvance();
    }).start();
    }
    }

    static class MarriagePhaser extends Phaser{
    @Override
    protected boolean onAdvance(int phase, int registeredParties) {
    switch (phase){
    case 0:
    System.out.println("所有人都到齐了");
    return false;
    case 1:
    System.out.println("可以开始吃了");
    return false;
    case 2:
    System.out.println("所有人离开了!");
    System.out.println("婚礼结束!");
    return true;
    default :
    return true;
    }
    }
    }

    static class Person{
    String name;

    public Person(String name) {
    this.name = name;
    }

    public void arrive() {
    System.out.printf("%s 到达现场! ", name);
    }

    public void eat() {
    System.out.printf("%s 吃完! ", name);
    }

    public void leave() {
    System.out.printf("%s 离开! ", name);
    }

    }

    它支持任务在多个点都进行同步,支持动态调整注册任务的数量。当然你也可以使用CountDownLatch,但你必须创建多个CountDownLatch对象,每一阶段都需要一个CountDownLatch对象。

    ReadWriteLock


    private static void userReadWriteLock(){
    ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    Lock readlock = readWriteLock.readLock();
    Lock writelock = readWriteLock.writeLock();
    Runnable readR = ()-> read(readlock);
    //Runnable writeR = ()->write(lock, new Random().nextInt());
    Runnable writeR = ()->write(writelock);

    for(int i=0; i<18; i++) new Thread(readR).start();
    for(int i=0; i<2; i++) new Thread(writeR).start();
    }

    public static void read(Lock lock){
    lock.lock();
    try {
    TimeUnit.SECONDS.sleep(1);
    System.out.println("read over!");
    //模拟读取操作
    } catch (InterruptedException e) {
    e.printStackTrace();
    }finally {
    lock.unlock();
    }
    }

    public static void write(Lock lock){
    lock.lock();
    try {
    TimeUnit.SECONDS.sleep(1);
    System.out.println("write over!");
    //模拟写操作
    } catch (InterruptedException e) {
    e.printStackTrace();
    }finally {
    lock.unlock();
    }
    }

  • 相关阅读:
    【unity3d游戏开发之基础篇】unity3d射线的原理用法以及一个利用射线实现简单拾取的小例子
    【unity3d游戏开发之疑难杂症】Unity3d工程如何与MonoDevelop工具进行调试
    【unity3d游戏开发之疑难杂症】解决Unity3d脚本支持中文问题
    cocos2d 中添加显示文字的三种方式(CCLabelTTF 、CCLabelBMFont 和CCLabelAtlas)
    xcode连不上ipad的原因
    【unity3d游戏开发之疑难杂症】Error while importing package: Couldn't decompress package
    AS3 event flow 事件冒泡机制 以及 stopImmediatePropagation() stopPropagation()用法
    【unity3d游戏开发之基础篇】利用射线实现鼠标控制角色转向和移动(角色移动一)
    Asp.net Session认识加强Session究竟是如何存储你知道吗?
    Windows 7下VS2008无法调试2.0.50727.4952版本mscorlib.dll的解决办法
  • 原文地址:https://www.cnblogs.com/btdxqz/p/12793701.html
Copyright © 2011-2022 走看看