并发工具类

1.CountDownLatch:可以实现线程计数,阻塞后续线程
                CountDownLatch类位于java.util.concurrent包下,利用它可以实现类似计数器的功能。比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,

     此时就可以利用CountDownLatch来实现这种功能了。
                countDown()实现计数器-1
                await()等待拦截方法,等待计数器为0时再放行,否则则一直阻塞
                getCount()获取当前计数器中计数数量
                
                案例:

                    /**
                     * 等待子线程全部执行完毕之后再执行主线程内容
                     * @param args
                     */
                    private static CountDownLatch countDownLatch=new CountDownLatch(2);
                    public static void main(String[] args) throws InterruptedException {
                        System.out.println("======主线程开始运行=====");
                        //第一个子线程
                        new Thread(()->{
                            System.out.println("子线程"+Thread.currentThread().getName()+"开始运行~");
                            //线程数量-1操作,通知该线程运行完毕
                            countDownLatch.countDown();
                        }).start();

                        //第二个子线程
                        new Thread(()->{
                            System.out.println("子线程"+Thread.currentThread().getName()+"开始运行~");
                            //线程数量-1操作,通知该线程运行完毕
                            countDownLatch.countDown();
                        }).start();

                        //等待,等待计数器中线程计数为0时才继续向下执行
                        countDownLatch.await();
                        System.out.println("子线程执行完毕,主线程继续执行");



                        //获取当前计数线程数量
                        /*while (true){
                            if(countDownLatch.getCount()==0){
                                System.out.println("子线程执行完毕,主线程继续执行");
                                break;
                            }
                        }*/
                    }
                

                
                
            2.CyclicBarrier:类似于栅栏,进行拦截,等待所有线程都准备,然后统一放行,阻塞当前线程

                //设置等待线程数量,当线程数量到达指定数量时,统一向下运行
                private static CyclicBarrier cyclicBarrier=new CyclicBarrier(10);
                public static void main(String[] args) {
                    //创建10个线程
                    for (int i = 1; i <=10 ; i++) {
                        new Thread(()->{
                            try {
                                Thread.sleep(100);
                                System.out.println(Thread.currentThread().getName()+"准备就绪");
                                //等待
                                cyclicBarrier.await();
                            } catch (InterruptedException | BrokenBarrierException e) {
                                e.printStackTrace();
                            }
                            System.out.println(Thread.currentThread().getName()+"开始比赛~");
                        }).start();
                    }
                }


            3.Semaphore:可以做资源控制,容器中有几个资源,那么线程执行时先申请资源,资源如果可用则继续执行,如果资源不可用则阻塞等待
                         当资源占用完毕之后将该资源释放,其他线程排队占用
               

                    //最多允许三个线程同时执行    
        private static Semaphore semaphore=new Semaphore(3);
                    public static void main(String[] args) {
                        for (int i = 1; i <=5 ; i++) {
                            new Thread(()->{
                                try {
                                    //申请资源,发生阻塞
                                    System.out.println(Thread.currentThread().getName()+"申请车位~");
                                    semaphore.acquire();
                                    System.out.println(Thread.currentThread().getName()+"可以停车了");
                                    //模拟上厕所时间
                                    Thread.sleep(1000);
                                    System.out.println(Thread.currentThread().getName()+"溜了溜了~");
                                    //释放资源
                                    semaphore.release();
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }).start();
                        }
                    }


                
            4.Exchanger:可以执行线程的资源交换,线程数量必须为偶数,因为是两两相互交换资源,如果不是偶数默认情况下导致阻塞,可以设置交换资源超时时间

    private static String str1="资源1";
    private static String str2="资源2";
    //构建资源交换对象
    private static Exchanger<String> stringExchanger=new Exchanger<>();
    public static void main(String[] args) {
        //第一个线程
        new Thread(()->{
            System.out.println(Thread.currentThread().getName()+"初始占用资源:"+str1);
            //资源交换,将资源交给其他线程和获取到其他线程交换过来的资源
            try {
                String newStr = stringExchanger.exchange(str1);
                System.out.println(Thread.currentThread().getName()+"交换资源:"+newStr);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        //第二个线程
        new Thread(()->{
            System.out.println(Thread.currentThread().getName()+"初始占用资源:"+str2);
            //资源交换,将资源交给其他线程和获取到其他线程交换过来的资源
            try {
                String newStr = stringExchanger.exchange(str2);
                System.out.println(Thread.currentThread().getName()+"交换资源:"+newStr);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        //第三个线程
        new Thread(()->{
            System.out.println(Thread.currentThread().getName()+"初始占用资源:"+str2);
            //资源交换,将资源交给其他线程和获取到其他线程交换过来的资源
            try {
                String newStr = stringExchanger.exchange(str2,1000, TimeUnit.MILLISECONDS);
                System.out.println(Thread.currentThread().getName()+"交换资源:"+newStr);
            } catch (InterruptedException | TimeoutException e) {
                e.printStackTrace();
            }
        }).start();
    }

原文地址:https://www.cnblogs.com/chx9832/p/12524379.html