• JUC(个人笔记二)衔接JUC个人笔记一


    8、常用的辅助类

    8.1 CountDownLatch(减法计数器)
    在这里插入图片描述

    package com.itheima.kiki.add;
    import java.util.concurrent.CountDownLatch;
    /**
     * @author kiki
     * @version 1.0
     * @create 2020/6/5 14:14
     */
    public class CountDownLatchDemo {
        public static void main(String[] args) throws InterruptedException {
            //倒计时,总数是6,一般用在必须要执行任务的时候再使用
            CountDownLatch countDownLatch = new CountDownLatch(6);
            for (int i = 1; i <= 6; i++) {
                new Thread(()->{
                    System.out.println(Thread.currentThread().getName()+"Go out");
                    countDownLatch.countDown();//数量减一
                },String.valueOf(i)).start();
            }
            countDownLatch.await();//等待计数器归零,然后再向下执行
            System.out.println("Close door");
        }
    }
    

    原理:
    countDownLatch.countDown();//数量减一
    countDownLatch.await();//等待计数器归零,然后再向下执行
    每次有线程调用countDown()数量-1,假设计数器变为0,countDownLatch.await()就会被唤醒,继续执行。

    8.2 CyclicBarrier(加法计数器)
    在这里插入图片描述

    package com.itheima.kiki.add;
    import java.util.concurrent.BrokenBarrierException;
    import java.util.concurrent.CyclicBarrier;
    /**
     * @author kiki
     * @version 1.0
     * @create 2020/6/5 15:12
     */
    public class CyclicBarrierDemo {
        public static void main(String[] args) {
            CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
                System.out.println("召唤神龙成功");
            });
            for (int i = 1; i <= 7; i++) {
                final int temp = i;
                //lambda能直接操作i吗?不能
                new Thread(()->{
                    System.out.println(Thread.currentThread().getName()+"收集"+temp+"颗龙珠");
                    try {
                        cyclicBarrier.await();//等待
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }).start();
            }
        }
    }
    

    8.3 Semaphore(并发里用的比较多)信号量

    package com.itheima.kiki.add;
    import java.util.concurrent.Semaphore;
    import java.util.concurrent.TimeUnit;
    /**
     * @author zs
     * @version 1.0
     * @create 2020/6/5 15:22
     */
    public class SemaphoreDemo {
        public static void main(String[] args) {
            //线程数量:3个停车位 限流的时候也会用!
            Semaphore semaphore = new Semaphore(3);
            for (int i = 1; i <= 6; i++) {
                new Thread(()->{
                    //acquire() 得到
                    try {
                        semaphore.acquire();
                        System.out.println(Thread.currentThread().getName()+"抢到车位");
                        TimeUnit.SECONDS.sleep(2);
                        System.out.println(Thread.currentThread().getName()+"离开车位");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        semaphore.release();//release() 释放
                    }
                },String.valueOf(i)).start();
            }
        }
    }
    

    原理:
    semaphore.acquire(); 获得,假设已经满了,等待到被释放为止
    semaphore.release();//release() 释放,会将当前的信号量释放+1,然后唤醒等待的线程
    作用:
    多个共享资源互斥的使用!并发限流,控制最大的线程数!

    9、读写锁

    ReadWriteLock
    在这里插入图片描述

    package com.itheima.kiki.rw;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReadWriteLock;
    import java.util.concurrent.locks.ReentrantLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    /**
     * @author kiki
     * @version 1.0
     * @create 2020/6/5 15:55
     */
    
    /**
     * 独占锁(写锁) 一次只能被一个线程占有
     * 共享锁(读锁) 多个线程可以同时占有
     * ReadWriteLock
     * 读和读   可以共存
     * 读和写  不可共存
     * 写跟写  不可共存
     */
    public class ReadWriteLockDemo {
        public static void main(String[] args) {
            //MyCache myCache = new MyCache();
            MyCacheLock myCacheLock = new MyCacheLock();
            //写入
            for (int i = 1; i <= 5; i++) {
                final int temp = i;
                new Thread(()->{
                    myCacheLock.put(temp+"",temp+"");
                },String.valueOf(i)).start();
            }
    
            //读取
            for (int i = 1; i <= 5; i++) {
                final int temp = i;
                new Thread(()->{
                    myCacheLock.get(temp+"");
                },String.valueOf(i)).start();
            }
            //2写入2
    		//2写入OK2
    		//3写入3
    		//3写入OK3
    		//写入4
    		//4写入OK4
    		//2读取2
    		//2读取OK2
    		//5写入5
    		//5写入OK5
        }
    }
    
    
    //加锁
    class MyCacheLock{
        private volatile Map<String,Object> map = new HashMap<>();
        //读写锁,更加细粒度的控制
        private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
        //private Lock lock = new ReentrantLock(); 没有更加细粒度
        //存,写,写入的时候只希望同时只有一个线程写
        public void put(String key,Object value){
            readWriteLock.writeLock().lock();//加锁
    
            try {
                System.out.println(Thread.currentThread().getName()+"写入"+key);
                map.put(key,value);
                System.out.println(Thread.currentThread().getName()+"写入OK"+key);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                readWriteLock.writeLock().unlock();//解锁
            }
        }
        //取,读,所有人可以读
        public void  get(String key){
            readWriteLock.readLock().lock();
            try {
                System.out.println(Thread.currentThread().getName()+"读取"+key);
                Object o = map.get(key);
                System.out.println(Thread.currentThread().getName()+"读取OK"+key);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                readWriteLock.readLock().unlock();
            }
        }
    }
    
    
    /**
     * 自定义缓存
     */
    class MyCache{
        private volatile Map<String,Object> map = new HashMap<>();
        //存,写
        public void put(String key,Object value){
            System.out.println(Thread.currentThread().getName()+"写入"+key);
            map.put(key,value);
            System.out.println(Thread.currentThread().getName()+"写入OK"+key);
        }
        //取,读![在这里插入图片描述](https://img-blog.csdnimg.cn/20200605165234816.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NjE2NTAz,size_16,color_FFFFFF,t_70)
        public void  get(String key){
            System.out.println(Thread.currentThread().getName()+"读取"+key);
            Object o = map.get(key);
            System.out.println(Thread.currentThread().getName()+"读取OK"+key);
        }
    }
    

    10、阻塞队列

    在这里插入图片描述
    阻塞队列:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    BlockingQueue 不是新的东西

    什么情况下我们会使用阻塞队列:多线程并发处理,线程池!
    学会使用队列
    四组API
    1、抛出异常

    package com.itheima.kiki.bq;
    import java.util.concurrent.ArrayBlockingQueue;
    /**
     * @author kiki
     * @version 1.0
     * @create 2020/6/5 16:56
     */
    public class Test {
        //BlockingQueue 不是新的东西
        public static void main(String[] args) {
            test1();
        }
        /**
         * 抛出异常
         */
        public static void test1(){
            //队列的大小
            ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
            System.out.println(blockingQueue.add("a"));
            System.out.println(blockingQueue.add("b"));
            System.out.println(blockingQueue.add("c"));
            System.out.println(blockingQueue.element());//返回对首元素
            //java.lang.IllegalStateException: Queue full
            //System.out.println(blockingQueue.add("d"));
    
            System.out.println("==============================");
            System.out.println(blockingQueue.remove());
            System.out.println(blockingQueue.remove());
            System.out.println(blockingQueue.remove());
            //java.util.NoSuchElementException
            //System.out.println(blockingQueue.remove());
        }
    
    }
    
    

    2、不会抛出异常

    public void test2(){
            //不抛出异常
            //队列的大小
            ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
            System.out.println(blockingQueue.offer("a"));
            System.out.println(blockingQueue.offer("b"));
            System.out.println(blockingQueue.offer("c"));
            System.out.println(blockingQueue.peek()); //检测对首元素
            //System.out.println(blockingQueue.offer("d")); //false 不抛出异常
            System.out.println("=========================");
            System.out.println(blockingQueue.poll());
            System.out.println(blockingQueue.poll());
            System.out.println(blockingQueue.poll());
            System.out.println(blockingQueue.poll());//null 也不抛出异常
    
        }
    

    3、阻塞等待

      /**
         * 阻塞等待(一直阻塞)
         */
        public void test3() throws InterruptedException {
            //队列的大小
            ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
    
            //一直阻塞
            blockingQueue.put("a"); //没有返回值
            blockingQueue.put("b");
            blockingQueue.put("c");
            //blockingQueue.put("d"); //对列没有位置了,一直阻塞
            System.out.println(blockingQueue.take());//取出元素
            System.out.println(blockingQueue.take());
            System.out.println(blockingQueue.take());
            //System.out.println(blockingQueue.take());//没有这个元素,一直阻塞
    
        }
    

    4、超时等待

        /**
         * 等待阻塞(等待超时)
         *
         */
        public void test4() throws InterruptedException {
            //队列的大小
            ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
    
            blockingQueue.offer("a");
            blockingQueue.offer("b");
            blockingQueue.offer("c");
            blockingQueue.offer("d", 2,TimeUnit.SECONDS);//等待超过两秒如果还没有位置就超时退出
    
            System.out.println("===============");
            System.out.println(blockingQueue.poll());
            System.out.println(blockingQueue.poll());
            System.out.println(blockingQueue.poll());
            blockingQueue.poll(2,TimeUnit.SECONDS); //等待超过两秒就退出
        }
    

    SynchronousQueue 同步队列
    没有容量
    进去一个元素,必须等待取出来之后,才能往里边放一个元素

    import java.util.concurrent.SynchronousQueue;
    import java.util.concurrent.TimeUnit;
    /**
     * @author kiki
     * @version 1.0
     * @create 2020/6/6 8:22
     */
    /**
     * 同步队列和其他BlockingQueue不一样,SynchronousQueue 不存储元素
     * put了一个元素必须从里边先take取出来,否则不能再put值
     */
    public class SynchronousQueueDemo {
        public static void main(String[] args) {
            BlockingQueue<String> blockingQueue = new SynchronousQueue<String>();
    
            new Thread(()->{
                try {
                    System.out.println(Thread.currentThread().getName()+"put 1");
                    blockingQueue.put("1");
                    System.out.println(Thread.currentThread().getName()+"put 2");
                    blockingQueue.put("2");
                    System.out.println(Thread.currentThread().getName()+"put 3");
                    blockingQueue.put("3");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            },"T1").start();
    
    
            new Thread(()->{
                try {
                    TimeUnit.SECONDS.sleep(3);
                    System.out.println(Thread.currentThread().getName()+blockingQueue.take());
                    TimeUnit.SECONDS.sleep(3);
                    System.out.println(Thread.currentThread().getName()+blockingQueue.take());
                    TimeUnit.SECONDS.sleep(3);
                    System.out.println(Thread.currentThread().getName()+blockingQueue.take());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            },"T2").start();
        }
    }
    
    

    11、线程池(重点)

    线程池:三大方法、七大参数、4种拒绝策略
    池化技术
    程序的运行,本质:占用系统的资源!优化资源的使用!=>池化技术
    线程池、JDBC连接池、内存池、对象池…
    池化技术:事先准备好一些资源,有人要用就来我这里拿,用完之后还给我

    线程池的好处:
    1、降低资源消耗
    2、提高响应的速度
    3、方便管理

    线程复用可以控制最大并发数、管理线程
    线程池三大方法

    package com.itheima.kiki.pool;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * @author kiki
     * @version 1.0
     * @create 2020/6/6 8:41
     */
    
    /**
     * Executors 工具类 3大方法
     * 使用了线程池之后,使用线程池来创建线程
     */
    public class ExecutorsDemo01 {
        public static void main(String[] args) {
            ExecutorService threadPool = Executors.newSingleThreadExecutor();//单个线程
            //ExecutorService threadPool = Executors.newFixedThreadPool(5);    //创建一个固定线程池的大小
            //ExecutorService threadPool = Executors.newCachedThreadPool();      //可以伸缩的
            try {
                for (int i = 1; i <= 10; i++) {
                    //使用了线程池之后,使用线程池来创建线程
                    threadPool.execute(()->{
                        System.out.println(Thread.currentThread().getName()+"OK");
                    });
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //线程池使用完之后,程序结束,关闭线程池
                threadPool.shutdown();
            }
    
        }
    }
    

    七大参数

    源码分析
     public static ExecutorService newSingleThreadExecutor() {
            return new FinalizableDelegatedExecutorService
                (new ThreadPoolExecutor(1, 1,
                                        0L, TimeUnit.MILLISECONDS,
                                        new LinkedBlockingQueue<Runnable>()));
        }
    
    
     public static ExecutorService newFixedThreadPool(int nThreads) {
            return new ThreadPoolExecutor(nThreads, nThreads,
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue<Runnable>());
        }
    
     public static ExecutorService newCachedThreadPool() {
            return new ThreadPoolExecutor(0, Integer.MAX_VALUE,//约等于21亿 OOM
                                          60L, TimeUnit.SECONDS, 
                                          new SynchronousQueue<Runnable>());
        }
    
    //本质:ThreadPoolExecutor
     public ThreadPoolExecutor(int corePoolSize,	//核心线程池大小
                                  int maximumPoolSize,//最大核心线程池大小
                                  long keepAliveTime,//超时了没有人调用就会释放
                                  TimeUnit unit,	//超时单位
                                  BlockingQueue<Runnable> workQueue, //阻塞队列
                                  ThreadFactory threadFactory,	//线程工厂,创建线程的,一般不用动
                                  RejectedExecutionHandler handler) {//拒绝处理策略
            if (corePoolSize < 0 ||
                maximumPoolSize <= 0 ||
                maximumPoolSize < corePoolSize ||
                keepAliveTime < 0)
                throw new IllegalArgumentException();
            if (workQueue == null || threadFactory == null || handler == null)
                throw new NullPointerException();
            this.corePoolSize = corePoolSize;
            this.maximumPoolSize = maximumPoolSize;
            this.workQueue = workQueue;
            this.keepAliveTime = unit.toNanos(keepAliveTime);
            this.threadFactory = threadFactory;
            this.handler = handler;
        }
    

    在这里插入图片描述
    在这里插入图片描述
    手动创建线程池
    四种拒绝策略
    在这里插入图片描述
    手动创建线程池

    package com.itheima.kiki.pool;
    import java.util.concurrent.*;
    /**
     * @author kiki
     * @version 1.0
     * @create 2020/6/6 8:41
     */
    /**
     * Executors 工具类 3大方法
     * 使用了线程池之后,使用线程池来创建线程
     */
    public class ExecutorsDemo02 {
        public static void main(String[] args) {
            /**
             * 参数1:核心大小
             * 参数2:最大
             * 参数3:超时等待,(比如:3,4,5号窗口一个小时都没有业务,就关闭,也就是所谓的线程池被释放了)
             * 参数4:阻塞(候客区)
             */
            //自定义线程池ThreadPoolExecutor
            ExecutorService threadPool = new ThreadPoolExecutor(2,
                                                                5,
                                                                3,
                                                                TimeUnit.SECONDS,
                                                                new LinkedBlockingDeque<>(3),
                                                                Executors.defaultThreadFactory(),
                                                                //AbortPolicy()  队列满了,银行满了,还有人进来,抛出异常
                                                                //CallerRunsPolicy() 哪来的去哪里
                                                                //DiscardPolicy() 队列满了(丢掉任务)不会抛出异常
                                                                //DiscardOldestPolicy() 队列满了,尝试和最早的竞争,也不会抛出异常
                                                                new ThreadPoolExecutor.DiscardOldestPolicy());
            try {
                //最大承载:Deque + max
                //超出最大承载抛出java.util.concurrent.RejectedExecutionException
                for (int i = 1; i <= 8; i++) {
                    //使用了线程池之后,使用线程池来创建线程
                    threadPool.execute(()->{
                        System.out.println(Thread.currentThread().getName()+"OK");
                    });
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //线程池使用完之后,程序结束,关闭线程池
                threadPool.shutdown();
            }
    
        }
    }
    

    了解:IO密集型、CPU密集型(调优)
    最大线程到底如何定义(池的最大大小如何去设置)
    1、CPU 密集型 几核就是几(12核就是12条线程) 可以保持CPU的效率最高
    2、IO 密集型 >判断你程序中十分耗IO的线程
    程序 15个大型任务,io十分占用资源

    12、四大函数式接口(必须掌握)

    新时代程序员:lambda表达式,链式编程,函数式接口,Stream流式计算
    函数式接口是什么?只有一个方法的接口

    @FunctionalInterface
    public interface Runnable {
        public abstract void run();
    }
    //超级多FunctionInterface
    //简化编程模型,在新版本的框架底层大量应用
    
    

    foreach参数都有什么?分别什么意思?
    答:消费者类型的函数式接口
    四大函数式接口

    一、Function
    在这里插入图片描述

    package com.itheima.kiki.function;
    /**
     * @author kiki
     * @version 1.0
     * @create 2020/6/6 12:16
     */
    import java.util.function.Function;
    /**
     * Function函数型接口,有一个输入参数,有一个输出
     * 只要是函数式接口就可以用Lambda表达式简化
     */
    public class FunctionDemo01 {
        public static void main(String[] args) {
            //工具类,输出输入的值
           /* Function function = new Function<String,String>() {
                @Override
                public String apply(String str) {
                    return str;
                }
            };*/
            Function<String,String> function =(str)->{return str;};
            System.out.println(function.apply("hello kiki"));
        }
    }
    

    二、Predicate
    在这里插入图片描述
    断定型接口
    有一个输入参数,返回值只能是布尔值

    package com.itheima.kiki.function;
    import java.util.function.Predicate;
    /**
     * @author kiki
     * @version 1.0
     * @create 2020/6/6 12:34
     */
    //断定型接口,有一个输入参数,返回值只能是布尔值
    public class PredicateDemo01 {
        public static void main(String[] args) {
            //判断字符串是否为空
            /*Predicate<String> predicate = new Predicate<String>() {
                @Override
                public boolean test(String str) {
                    return str.isEmpty();
                }
            };*/
            Predicate<String> predicate = (str)->{return str.isEmpty();};
            System.out.println(predicate.test("hello kiki"));
        }
    }
    

    三、Consumer 消费型接口
    在这里插入图片描述

    package com.itheima.kiki.function;
    import java.util.function.Consumer;
    
    /**
     * @author kiki
     * @version 1.0
     * @create 2020/6/6 13:14
     */
    
    /**
     * Consumer 消费型接口,只有输入,没有返回值
     */
    public class ConsumerDemo01 {
        public static void main(String[] args) {
         /*   Consumer<String> consumer = new Consumer<String>() {
                @Override
                public void accept(String str) {
                    System.out.println(str);
                }
            };*/
            Consumer<String> consumer = (str)->{System.out.println(str);};
    
            consumer.accept("hello kiki");
        }
    
    
    }
    

    四、Supplier 供给型接口
    在这里插入图片描述

    package com.itheima.kiki.function;
    
    import java.util.function.Supplier;
    
    /**
     * @author kiki
     * @version 1.0
     * @create 2020/6/6 13:24
     */
    
    /**
     * Supplier 供给型接口 没有参数,只有返回值
     */
    public class SupplierDemo01 {
        public static void main(String[] args) {
           /* Supplier supplier = new Supplier<Integer>() {
                @Override
                public Integer get() {
                    return 1024;
                }
            };*/
    
            Supplier supplier = ()->{return 1024;};
            System.out.println(supplier.get());
        }
    
    }
    

    13、Stream流计算

    什么是Stream流计算?
    大数据:存储+计算

    
    /**
     * @author zs
     * @version 1.0
     * @create 2020/6/6 13:38
     */
    public class Test {
        public static void main(String[] args) {
            User u1 = new User(1,"a",21);
            User u2 = new User(2,"b",22);
            User u3 = new User(3,"c",23);
            User u4 = new User(4,"d",24);
            User u5 = new User(6,"e",25);
    
            //集合就是存储
            List<User> list = Arrays.asList(u1, u2, u3, u4, u5);
    
            //计算交给Stream流
            list.stream()
                    .filter(u->{return u.getId()%2==0;})
                    .filter(u->{return u.getAge()>23;})
                    .map(u->{return u.getName().toUpperCase();})
                    .sorted((uu1,uu2)->{return uu2.compareTo(uu1);})
                    //只输出一个
                    .limit(1)
                    .forEach(System.out::println);
        }
    
    
    }
    
    

    14、ForkJoin

    什么是ForkJoin?
    ForkJoin在JDK1.7之后,并行执行任务,提高效率。大数据量!(几十亿)
    大数据:Map Reduce(把大任务拆分成小任务)
    ForkJoin特点:工作窃取(它维护了一个双端队列)
    在这里插入图片描述

    package com.itheima.kiki.forkjoin;
    
    /**
     * @author kiki
     * @version 1.0
     * @create 2020/6/6 15:37
     */
    
    import java.util.concurrent.RecursiveTask;
    
    /**求和计算的任务
     * 3000 6000(ForkJoin) 9000(Stream并行流)
     * 如何使用ForkJoin
     *      1、ForkJoinPool 通过它来执行
     *      2、计算任务ForkJoinPool.execute(ForkJoinTask task)
     *      3、计算类要继承ForkJoinTask
     */
    public class ForkJoinDemo extends RecursiveTask<Long> {
        private long start; //1
        private long end;   //1990900000
    
        //临界值
        private long temp = 10000L;
    
        public ForkJoinDemo(long start, long end) {
            this.start = start;
            this.end = end;
        }
    
        public static void main(String[] args) {
    
        }
    
        //计算方法
        @Override
        protected Long compute() {
            if (end-start<temp){
                //分支合并计算
                Long sum = 0L;
                for (int i = 1; i <= end; i++) {
                    sum+=i;
                }
                return sum;
    
            }else {//forkjoin
                long middle = (start+end)/2;//中间值
                ForkJoinDemo task1 = new ForkJoinDemo(start, middle);
                task1.fork();//拆分任务,把任务压入线程队列
                ForkJoinDemo task2 = new ForkJoinDemo(middle+1,end);
                task2.fork();   //拆分任务,把任务压入线程队列
    
                return task1.join()+task2.join();
            }
    
        }
    }
    

    测试

    package com.itheima.kiki.forkjoin;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ForkJoinPool;
    import java.util.concurrent.ForkJoinTask;
    import java.util.stream.LongStream;
    /**
     * @author kiki
     * @version 1.0
     * @create 2020/6/6 16:04
     */
    public class Test {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            //test1();//12224ms
            //test2(); //10038
            //test3(); //138
        }
        public static void test1(){
            long sum = 0;
            long start = System.currentTimeMillis();
            for (Long i = 1L; i < 10_0000_0000; i++) {
                sum+=i;
            }
            long end = System.currentTimeMillis();
            System.out.println("sum="+"时间:"+(end-start));
    
        }
        //会使用forkjoin的
        public static void test2() throws ExecutionException, InterruptedException {
            long start = System.currentTimeMillis();
            ForkJoinPool forkJoinPool = new ForkJoinPool();
            ForkJoinTask<Long> task = new ForkJoinDemo(0L,10_0000_0000L);
            //forkJoinPool.execute(task);//执行
            ForkJoinTask<Long> submit = forkJoinPool.submit(task);//提交任务
            Long sum = submit.get();//阻塞等待
            long end = System.currentTimeMillis();
            System.out.println("sum="+"时间:"+(end-start));
        }
        //Stream并行流
        public static void test3(){
            long start = System.currentTimeMillis();
            /**
             * Stream并行流
             * range()  ()
             * rangeClosed() (]
             */
            long sum = LongStream.rangeClosed(0L, 10_0000_0000L).parallel().reduce(0, Long::sum);
    
    
            long end = System.currentTimeMillis();
            System.out.println("sum="+"时间:"+(end-start));
        }
    
    }
    

    15、异步回调

    Future设计的初衷就是为了

    package com.itheima.kiki.future;
    
    /**
     * @author kiki
     * @version 1.0
     * @create 2020/6/6 16:34
     */
    
    import java.util.concurrent.CompletableFuture;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.TimeUnit;
    
    /**
     * 异步调用:CompletableFuture
     *      异步执行
     *      成功回调
     *      失败回调
     */
    public class FutureDemo01 {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
    //        //没有返回值的 runAsync 异步回调
    //        CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(()->{
    //            //异步任务发起的时候并不会占用时间
    //            try {
    //                TimeUnit.SECONDS.sleep(2);
    //            } catch (InterruptedException e) {
    //                e.printStackTrace();
    //            }
    //            System.out.println(Thread.currentThread().getName()+"runAsync=>Void");
    //        });
    //        System.out.println("122231");
    //        completableFuture.get();//阻塞获取执行结果
    
            //有返回值的异步回调
            //ajax 成功和失败的回调
            //返回的是错误信息
            CompletableFuture<Integer> completableFuture =CompletableFuture.supplyAsync(()->{
                System.out.println(Thread.currentThread().getName()+"supplyAsync=>Integer");
                //int i = 10/0; 手动制造异常
                return 1024;
            });
    
            System.out.println(completableFuture.whenComplete((t, u) -> {
                System.out.println("t=>" + t);  //正常的返回结果
                System.out.println("u=>" + u);  //打印错误信息
            }).exceptionally((e) -> {
                System.out.println(e.getMessage());
                return 233; //可以获取到错误的返回结果
            }).get());
    
    
        }
    
    }
    

    (内容接下一部分https://blog.csdn.net/qq_38616503/article/details/106519823)

  • 相关阅读:
    c#面向对象基础技能——学习笔记(五)委托技术在开发中的应用
    c#面向对象基础技能——学习笔记(三)基于OOP思想研究对象的【方法】
    c#面向对象基础技能——学习笔记(二)基于OOP思想研究对象的【属性】
    使用移位寄存器产生重复序列信号“100_0001”,移位寄存器的级数至少为?
    设计一个异步双端口RAM,深度为16,数据位宽为8bit
    soda水1块钱,硬币有五毛和一块两种:
    画状态机,接收1,2,5分钱的卖报机,每份报纸5分钱
    三极管
    画出可以检测10010串的状态图
    NOT、NAND、NOR符号
  • 原文地址:https://www.cnblogs.com/kiki-study/p/13656116.html
Copyright © 2020-2023  润新知