Java多线程API countDownlatch syslicbarrier semaphore详解以及使用

122 阅读2分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

CountDownLatch 让班长线程阻塞,直到同学线程CountDownLatch到0,再执行

让一些线程阻塞直到另一些线程完成一系列操作后才被唤醒

CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,调用线程会被阻塞。其它线程调用countDown方法会将计数器减1(调用countDown方法的线程不会阻塞),当计数器的值变为零时,因调用await方法被阻塞的线程会破唤醒,继续执行。

    火箭发射10 9 80
    await方法将会执行,直到计数到0
package com.wsx.countDown;

import java.util.concurrent.CountDownLatch;

    public class CountDownDemo {
        public static void main(String[] args) {
            CountDownLatch countDownLatch = new CountDownLatch(6);
            for (int i = 0; i < 6; i++) {
                new Thread(()->{
                    System.out.println(Thread.currentThread().getName()+"号同学离开");
                    countDownLatch.countDown();
                },String.valueOf(i)).start();
            }

            try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); }

            System.out.println(Thread.currentThread().getName()+"班长锁门");
        }
    }
复制代码

枚举 :相当于一个数据库 解耦合 不用建立连接关闭连接

package com.wsx.countDown;

    public enum  CountryEnum {
        ONE(1,"齐"),TWO(2,"楚"),THREE(3,"燕"),FOUR(4,"汉"),FIVE(5,"赵"),SIX(6,"魏");
        private Integer retCode;
        private String retName;

        public Integer getRetCode() {
            return retCode;
        }

        public void setRetCode(Integer retCode) {
            this.retCode = retCode;
        }

        public String getRetName() {
            return retName;
        }

        public void setRetName(String retName) {
            this.retName = retName;
        }

        CountryEnum(Integer retCode, String retName) {
            this.retCode = retCode;
            this.retName = retName;
        }
        public static CountryEnum findCountry(int index){
            CountryEnum[] values = CountryEnum.values();
            for (CountryEnum element:values) {
                if(index == element.getRetCode()){
                    return element;
                }
            }
            return null;
        }
    }
复制代码
package com.wsx.countDown;

import java.util.concurrent.CountDownLatch;

    public class CountDownDemo2 {
        public static void main(String[] args) {
            CountDownLatch countDownLatch = new CountDownLatch(6);
            for (int i = 1; i <= 6; i++) {
                new Thread(()->{
                    System.out.println(Thread.currentThread().getName()+"国被灭");
                    countDownLatch.countDown();
                },CountryEnum.findCountry(i).getRetName()).start();
            }

            try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); }

            System.out.println(Thread.currentThread().getName()+"秦国赢");
        }
    }
复制代码

CyclicBarrier

举例:到一个屏障点,到七个龙珠都集齐才能召唤神龙,找到第一个,要等剩下的六个都找到,再继续工作

CyclicBarrier的字面意思是可循环(Cyclic) 使用的屏障(Barrier) 。它要做的事情是,让一-组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过CyclicBarrier的await)方法。 内存屏障点

package com.wsx.cyclicBarrier;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

    public class CyclicBarrierDemo {
        public static void main(String[] args) {
            CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
                System.out.println("召唤神龙");
            });

            for (int i = 1; i <= 7; i++) {
                int tempint = i;
                new Thread(()->{
                    System.out.println(Thread.currentThread().getName()+"第"+tempint+"龙珠");
                    try {
                        cyclicBarrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                },String.valueOf(i)).start();
            }
        }
    }
复制代码

Semaphore

有一个上限,假如,两个车位车位相当于限制并发数量,四个车,需要前两个车停完之后,其他的车才能再来停(争车位,抢红包,秒杀,电商并发,微信红包)

多个线程抢多个资源

信号量主要用于两个目的,一个是用于多个共享资源的互斥使用,另-一个用于并发线程数的控制。

package com.wsx.semaPhore;

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

    public class SemaPhoreDemo {
        public static void main(String[] args) {
            Semaphore semaphore = new Semaphore(2);
            for (int i = 1; i <= 4; i++) {
                new Thread(()->{
                    try {
                        semaphore.acquire();
                        System.out.println(Thread.currentThread().getName()+"号停车");
                        TimeUnit.SECONDS.sleep(3);
                        System.out.println(Thread.currentThread().getName()+"号离开");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        semaphore.release();
                    }
                },String.valueOf(i)).start();
            }
        }
    }