线程池

池化技术
程序运行的本质:占用系统的资源,优化资源的使用 => 线程池,JDBC连接池,内存池,对象池

事先准备好一些资源,有人要用,就来我这里拿,用完之后还给我

  1. 最小连接数
  2. 最大连接数

线程池的好处?

  • 减低资源消耗
  • 提高响应效率(创建和销毁十分浪费资源)
  • 方便管理

线程可以复用,可以控制最大并发数,管理线程

线程池:三大方法,七大参数,四种拒绝策略

阿里巴巴多线程规约:线程不允许使用Executors创建,而是通过ThreadPoolExecutor的方式,这种处理方式让写的同学更加明确线程池的运行规则,避免资源耗尽的风险

三大方法

public class Demo01 {
    public static void main(String[] args) {
        //Executors 一个工具类,三大方法
        //ExecutorService threadPool = Executors.newSingleThreadExecutor();//创建一个单个线程数的线程池
        //ExecutorService threadPool = Executors.newFixedThreadPool(5);  //创建一个固定线程数的线程池
         ExecutorService threadPool = Executors.newCachedThreadPool();   //遇强则强,遇弱则弱


        try {
            for (int i = 0; i < 100; i++) {
                // new Thread().start();  传统方式
                //使用线程池创建
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + " ok");
                });
            }
            } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //程序结束需要关闭线程池
            threadPool.shutdown();
        }
    }
}

源码分析

  public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>(),
                                      threadFactory);
    }
  public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>(),
                                    threadFactory));
    }
  public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

七大参数

本质

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;
    }

四种拒绝策略(当候客区(阻塞队列)已满 而且 已达最大线程并发量时拒绝先来的请求)

默认拒绝策略

  • AbortPolicy():默认拒绝策略 线程满了,阻塞队列满了,做不处理处理方式,并且抛出异常
  • CallerRunsPolicy(): 哪里来的去哪里 main ok
  • DiscardPolicy():队列满了不会抛出异常,会丢掉任务
  • DiscardOldestPolicy():队列满了会尝试去和第一个使用线程的竞争,如果竞争不过则会丢掉任务
public class Demo02 {
    public static void main(String[] args) {
        //自定义线程池
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
                2,
                5,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(3),  //候客区,即阻塞队列
                Executors.defaultThreadFactory(),  //默认线程工厂
                //new ThreadPoolExecutor.AbortPolicy());  //默认拒绝策略 线程满了,阻塞队列满了,做不处理处理方式,并且抛出异常
                //new ThreadPoolExecutor.CallerRunsPolicy());  //哪里来的去哪里  main ok
                //new ThreadPoolExecutor.DiscardOldestPolicy());  //队列满了会尝试去和第一个使用线程的竞争,如果竞争不过则会丢掉任务
                new ThreadPoolExecutor.DiscardPolicy());  //队列满了不会抛出异常,会丢掉任务
        try {
            //最大承载=阻塞队列大小+最大线程池数目
            //超出最大承载会抛出异常
            for (int i = 0; i < 9; i++) {
                // new Thread().start();  传统方式
                //使用线程池创建
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + " ok");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //程序结束需要关闭线程池
            threadPool.shutdown();
        }
    }
}
posted @ 2022-01-15 17:32  一刹流云散  阅读(27)  评论(0编辑  收藏  举报