• JDK提供的并发工具类


    1.CountDownLatch

    await(),进入等待的状态
    countDown(),计数器减一
    应用场景:启动三个线程计算,需要对结果进行累加。

    /**
     * 
     * CountDownLatch Demo
     * 
     */
    public class CountDownLatchDemo {
    
        public static void main(String[] args) {
    
            CountDownLatch countDownLatch = new CountDownLatch(8);
            new Thread(()->{
    
                try {
                    countDownLatch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                System.out.println("800米比赛结束,准备清空跑道并继续跨栏比赛");
            }).start();
    
            for (int i = 0; i < 8; i++) {
    
                final  int finalI = i;
    //            System.out.println("fin->"+finalI);
                new Thread(()->{
    
                    try {
                        Thread.sleep(finalI * 1000L);
                        System.out.println(Thread.currentThread().getName()+"到达终点了");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        countDownLatch.countDown();
                    }
                }).start();
            }
        }
    }
    

    2.CyclicBarrier--栅栏

    允许一组线程相互等待达到一个公共的障碍点,之后再继续执行
    跟countDownLatch的区别
    CountDownLatch一般用于某个线程等待若干个其他线程执行完任务之后,它才执行;不可重复使用
    CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行;可重用的

    /**
     * 栅栏系统
     */
    public class CyclicBarrierDemo {
    
        public static void main(String[] args) {
    
            CyclicBarrier cyclicBarrier = new CyclicBarrier(8);
    
            for (int i = 0; i < 8; i++) {
    
                int finalI = i;
                new Thread(()->{
                    try {
                        Thread.sleep(finalI *1000L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"准备就绪");
    
                    try {
    
                        cyclicBarrier.await();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
    
                    System.out.println("开始比赛");
                }).start();
    
    
            }
        }
    
    }
    

    3.Semaphore--信号量

    控制并发数量
    使用场景:接口限流

    /**
     * Semaphore
     * 控制进来的最多的线程数量 等释放后才允许后续的进来
     */
    public class SemaphoreDemo {
    
        public static void main(String[] args) {
    
            Semaphore semaphore = new Semaphore(8);
    
            for (int i = 0; i < 10; i++) {
                new Thread(()->{
    
    
                    try {
                        semaphore.acquire();
                        System.out.println(Thread.currentThread().getName()+"开始执行");
                        Thread.sleep(5000L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        //最后需要释放
                        semaphore.release();
                    }
    
                }).start();
            }
        }
    }
    

    4.Exchanger

    用于交换数据
    它提供一个同步点,在这个同步点两个线程可以交换彼此的数据。这两个线程通过exchange方法交换数据,
    如果第一个线程先执行exchange方法,它会一直等待第二个线程也执行exchange,当两个线程都到达同步点
    时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方。因此使用Exchanger的重点是成对的
    线程使用exchange()方法,当有一对线程达到了同步点,就会进行交换数据。因此该工具类的线程对象是【成
    对】的。

    /**
     * Exchanger 线程间的数据交换
     * 交换线程数量必须成对
     *
     */
    public class ExchangerDemo {
    
        public static void main(String[] args) {
    
            Exchanger<String> stringExchanger = new Exchanger<>();
    
            String str1 = "str001";
            String str2 = "str002";
    
            new  Thread(()->{
    
                System.out.println(Thread.currentThread().getName()
                +"初始化的数据==>"+str1
                );
                try {
                    //开始交换数据
                    String exchange = stringExchanger.exchange(str1);
                    System.out.println(Thread.currentThread().getName()
                            +"交换后的数据==>"+exchange
                    );
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
    
            },"线程1").start();
    
            new  Thread(()->{
    
                System.out.println(Thread.currentThread().getName()
                        +"初始化的数据==>"+str2
                );
                try {
                    //开始交换数据
                    String exchange = stringExchanger.exchange(str2);
                    System.out.println(Thread.currentThread().getName()
                            +"交换后的数据==>"+exchange
                    );
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
    
            },"线程2").start();
    
        }
    
    }
    
    
  • 相关阅读:
    Redis--过期键策略(惰性删除、定期删除)
    Redis--数据库(个数16、键空间、过期字典、过期策略)
    Redis--事件(serverCron)
    ArrayList是如何扩容的?
    Java的四大引用类型
    类加载机制,双亲委派模型及其优点
    GC调优思路
    modcount的作用
    JVM的常见的垃圾收集器
    什么是临界区?如何解决冲突(也就是临界区的调度原则)?
  • 原文地址:https://www.cnblogs.com/charlypage/p/10897554.html
Copyright © 2020-2023  润新知