线程池
3大方法、7大参数、4种拒绝策略
好处:降低资源的消耗、提高响应的速度、方便管理、
线程池可以理解为银行业务

三大方法
        第1大方法:单个线程
                 ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
         第2大方法:创建一个固定的线程池大小
                 ExecutorService threadExecutor = Executors.newFixedThreadPool(int nThreads);
         第3大方法:可伸缩的,遇强则强,遇弱则弱
                 ExecutorService threadExecutor = Executors.newCachedThreadPool();
import java.util.concurrent.*;
//Executors 工具类 3大方法
public class Demo01 {
    public static void main(String[] args) {
        //单个线程
//        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        //固定大小
//        ExecutorService threadPool = Executors.newFixedThreadPool(5);
        //可伸缩的,遇强则强,遇弱则弱
//        ExecutorService threadPool = Executors.newCachedThreadPool();
        try {
            //最大承载:最大线程池大小 + 阻塞队列
            for (int i = 0; i < 10; i++) {
                //使用了线程池要用线程池来创建变量
                threadPool.execute(()->{
                    System.out.println(Thread.currentThread().getName()+" ok");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //线程池用完,程序结束,关闭线程池
            threadPool.shutdown();
        }
    }
}输出:
第1大方法:单个线程

第2大方法:创建一个固定的线程池大小(5)

第3大方法:可伸缩的,遇强则强,遇弱则弱

7大参数及自定义线程池
源码分析(3大方法)
    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,
                                      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.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }阿里巴巴开发手册中说明

手动创建线程池以及四种拒绝策略
public class Demo01 {
    public static void main(String[] args) {
        //自定义线程池
        ExecutorService threadExecutor = new ThreadPoolExecutor(
                2,
                5,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(3),
                Executors.defaultThreadFactory(),
                //队列满了,线程数达到最大线程数,还有线程过来,不处理这个线程,抛出异常
//                new ThreadPoolExecutor.AbortPolicy()
                //哪里来的就去哪里
//                new ThreadPoolExecutor.CallerRunsPolicy()
                //队列满了,丢掉任务,不会抛出异常
//                new ThreadPoolExecutor.DiscardPolicy()
                //队列满了,尝试和最早的竞争,竞争失败丢掉任务,也不会抛出异常
                new ThreadPoolExecutor.DiscardOldestPolicy()
        );
        try {
            //最大承载:Deque + Max  超过,RejectedExecutionException
            for (int i = 0; i < 9; i++) {
                //使用了线程池之后,使用线程池来创建线程
                threadExecutor.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + " ok");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //线程池用完,程序结束,关闭线程池
            threadExecutor.shutdown();
        }
    }
}new ThreadPoolExecutor.AbortPolicy() 输出

new ThreadPoolExecutor.CallerRunsPolicy() 输出

new ThreadPoolExecutor.DiscardPolicy() 输出

new ThreadPoolExecutor.DiscardOldestPolicy() 输出

四种拒绝策略小结

   1. 队列满了,线程数达到最大线程数,还有线程过来,不处理这个线程,抛出异常
         new ThreadPoolExecutor.AbortPolicy()
    2. 哪里来的就去哪里
         new ThreadPoolExecutor.CallerRunsPolicy()
    3. 队列满了,丢掉任务,不会抛出异常
         new ThreadPoolExecutor.DiscardPolicy()
     4. 队列满了,尝试和最早的竞争,竞争失败丢掉任务,也不会抛出异常
         new ThreadPoolExecutor.DiscardOldestPolicy()
最大线程应该如何设置
-  CPU密集型,几核,就是几,可以保证CPU效率最高 
-  IO密集型 (判断你程序中十分耗IO的线程) 如:程序中有15个大型任务,IO十分消耗资源,一般设置为2倍,为30 
获取CPU核数
//获取CPU核数
System.out.println(Runtime.getRuntime().availableProcessors());

自定义线程池代码优化
public class Demo01 {
    public static void main(String[] args) {
        //自定义线程池
        ExecutorService threadExecutor = new ThreadPoolExecutor(
                4,
                Runtime.getRuntime().availableProcessors(),
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(3),
                Executors.defaultThreadFactory(),
                //队列满了,丢掉任务,不会抛出异常
                new ThreadPoolExecutor.DiscardPolicy()
        );
        try {
            //最大承载:Deque + Max  超过,RejectedExecutionException
            for (int i = 0; i < 10; i++) {
                //使用了线程池之后,使用线程池来创建线程
                threadExecutor.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + " ok");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //线程池用完,程序结束,关闭线程池
            threadExecutor.shutdown();
        }
    }
}


















