zoukankan      html  css  js  c++  java
  • 并发工具类

    1.CountDownLatch

      CountDownLatch是一个同步计数器,初始化的时候传入需要计数的线程等待数,可以是需要等待执行完成的线程数,或者大于;

      作用:用来协调多个线程之间的同步,或者说起到线程之间的通信(而不是用作互斥的作用)。是一组线程等待其他的线程完成工作以后在执行,相当于加强版join;

      await():阻塞当前线程,等待其他线程执行完成,直达计数器计数值减到0;

      countDown():负责计算器的减一;

    package com.wn.Test01;
    
    import java.util.concurrent.CountDownLatch;
    
    public class CountDownLathTest01 {
        public static void main(String[] args) throws InterruptedException {
            System.out.println("等待子线程执行完毕......");
            final CountDownLatch countDownLatch=new CountDownLatch(2);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("子线程:"+Thread.currentThread().getName()+"开始执行......");
                    countDownLatch.countDown(); //每次减去1
                    System.out.println("子线程:"+Thread.currentThread().getName()+"结束执行......");
                }
            }).start();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("子线程:"+Thread.currentThread().getName()+"开始执行......");
                    countDownLatch.countDown();;
                    System.out.println("子线程:"+ Thread.currentThread().getName()+"结束执行......");
                }
            }).start();
            countDownLatch.await(); //调用当前方法主线程阻塞   countDown结果为0,阻塞变为运行状态
            System.out.println("两个子线程执行完毕......");
            System.out.println("继续主线程执行...");
    
        }
    }

    2.CyclicBarrier:

      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

      Semaphore有名信号量,是操作系统中的一个概念,在java并发编程中,信号量控制的是线程并发的数量;

      作用:Semaphore管理一系列许可证。每个acquire方法阻塞,直到有一个许可证可以获得然后拿走一个许可证;每个release方法增加一个许可证,这可能会释放一个阻塞的acquire方法。然而,其实并没有实际的许可证这个对象,Semaphore只是维持一个可获得许可证的数量,主要控制同时访问某个特定资源的线程数量,多用在流量控制;

      注意:其他Semaphore的底层显示就是基于AQS的共享锁实现的

      如果一个线程要访问共享资源,必须先获得信号量,如果信号量的计数器值大于1,意味着有共享资源可以访问,则使其计数器值减去1,在访问共享资源。如果计数器值为0,线程进入休眠。当某个线程使用完共享资源后,释放信号量,并将信号量内部的计数器加1,之间进入休眠的线程将被唤醒并再次试图获取信号量;

    private static Semaphore semaphore=new Semaphore(3);
                        public static void main(String[] args) {
                            for (int i = 1; i <=10 ; 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

      Exchanger类似于一个交换器,可以对元素进行配对和交换的线程的同步点,用于两个线程间的数据交换;

      具体来说,Exchanger类允许在两个线程之间定义同步点。当两个线程都到达同步点时,它们交换数据结构,因此第一个线程的数据结构进行第二个线程中,第二个线程的数据结构进入到第一个线程中;

      就像两个线程各个交换自己的数据;

    public class ExchangerDemo {
                        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();
                        }
                    }
  • 相关阅读:
    spring-boot启动debug信息中non-fatal error解决
    spring-boot-sample-web-jsp
    How to configure spring boot through annotations in order to have something similar to <jsp-config> in web.xml?
    mybatis支持属性使用驼峰的命名
    No handler for type [text] declared on field [content]
    android自定义控件库
    Android 百分比布局库(percent-support-lib) 解析与扩展
    Android 高清加载巨图方案 拒绝压缩图片
    Android 热补丁动态修复框架小结
    AndroidAutoLayout 屏幕适配
  • 原文地址:https://www.cnblogs.com/ws1149939228/p/12526330.html
Copyright © 2011-2022 走看看