线程池浅析

目录

导语

线程池作用

线程池的创建

线程池参数说明

线程的创建过程

后续


导语

​      线程的创建、启动、销毁等是一个非常消耗资源的过程。引出线程池。

 

线程池作用

  1. 降低资源消耗,重复利用已创建好的线程。
  2. 提高响应速度,通过已经创建好的线程直接执行到达的任务,无需等待。
  3. 线程的统一管理,对线程统一分配、监控和调优(专人专职)。

 

线程池的创建

线程池的四种创建方式,本质都是通过改变构造函数的参数来创建不同的线程的。最终调用的构造函数都是:

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

以下以demo分别说明线程池的创建:

一、创建缓存线程

        ExecutorService threadPool = Executors.newCachedThreadPool();
        for(int i=0;i<10;i++){
            int temp = i;
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+","+temp);
                }
            });
        }
        threadPool.shutdown();// 停掉线程池

二、创建固定长度的线程(常用)

        ExecutorService threadPool = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 10; i++) {
            int temp = i;
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+","+temp);
                }
            });
        }
        threadPool.shutdown();// 停掉线程池

三、创建定时线程

        ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(3);
        threadPool.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("我是定时线程,三秒后启动");
            }
        },3, TimeUnit.SECONDS); // 第一个参数是任务,第二个参数是时间长度,第三个参数时间单位
        threadPool.shutdown();// 停掉线程池

四、创建单线程

        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("我是单线程线程");
                }
            });
        }
        threadPool.shutdown();// 停掉线程池

 

线程池参数说明

重点:几乎是面试必问的。

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {}

corePoolSize:核心线程数

maximumPoolSize:最大线程数

keepAliveTimea:线程空闲时间

unit:TimeUnit枚举类型的值,代表keepAliveTime时间单位,可以取下列值:

  • TimeUnit.DAYS; //天   
  • TimeUnit.HOURS; //小时   
  • TimeUnit.MINUTES; //分钟   
  • TimeUnit.SECONDS; //秒   
  • TimeUnit.MILLISECONDS; //毫秒   
  • TimeUnit.MICROSECONDS; //微妙   
  • TimeUnit.NANOSECONDS; //纳秒

workQueue:阻塞队列,用来存储等待执行的任务,决定了线程池的排队策略,有以下取值:

  • ArrayBlockingQueue
  • LinkedBlockingQueue
  • SynchronousQueue

threadFactory:线程工厂,是用来创建线程的

handler:线程拒绝策略。当创建的线程超出maximumPoolSize,且缓冲队列已满时,新任务会拒绝,有以下取值:

  • ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
  • ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。    
  • ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)   
  • ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

 

线程的创建过程

下图是线程池的执行流程(图片摘自网络):

流程说明:

  1. 用户提交任务,先到核心线程池,判断核心线程池是都已满;
  2. 如何核心线程池未满,线程任务执行;如何核心线程已满,走下一步;
  3. 进入线程缓存队列,判断缓存队列是否已满;
  4. 如果线程缓存队列已满,进入最大线程池;
  5. 如果最大线程池未满,创建线程任务;
  6. 如果最大线程池已满,则拒绝。

 

后续

  1. 线程池核心参数的设置;
  2. 线程池的源码分析:
    • 执行流程细化
    • 缓存策略
    • 拒绝策略
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值