ThreadPoolExecutor线程池


小结:需要掌握,线程三大方法,7大参数,4大拒绝策略。
创建线程池时,不建议使用Executors创建,通过ThreadPoolExecutor方式创建规避资源耗尽的风险

创建线程的3大方法

ExecutorService threadExecutor = Executors.newSingleThreadExecutor();//单个线程
ExecutorService threadExecutor = Executors.newFixedThreadPool(5); //创建一个固定的线程池的大小
ExecutorService threadExecutor = Executors.newCachedThreadPool(); //可伸缩的,遇强则强,遇弱则弱

ThreadPoolExecutor7 大参数

操作:查看三大方法的底层源码,发现本质都是调用了 new ThreadPoolExecutor ( 7 大参数 )

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

参数理解:
corePollSize :核心线程数。在创建了线程池后,线程中没有任何线程,等到有任务到来时才创建,固定工作的线程
线程去执行任务。默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建
一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当
中。
maximumPoolSize:最大线程数。表明线程中最多能够创建的线程数量,此值必须大于等于1。
keepAliveTime :空闲的线程保留的时间。
TimeUnit:空闲线程的保留时间单位。

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

BlockingQueue< Runnable> :阻塞队列,存储等待执行的任务。参数有ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue可选。
ThreadFactory :线程工厂,用来创建线程,一般默认即可

RejectedExecutionHandler :队列已满,而且任务量大于最大线程的异常处理策略。有以下取值

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

ThreadPoolExecutor底层工作原理

在这里插入图片描述

四大拒绝策略

触发拒绝策略条件: 需要执行线程数 >= 核心线程数+队列数 。举例:执行线程数10,核心线程数5,队列数3 则会触发
不触发拒绝策略条件: 需要执行线程数 < 核心线程数+队列数 。举例:执行线程数10,核心线程数5,队列数6 不会触发

// 默认,队列满了丢任务,抛出异常
RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy(); 
// 丢弃任务,但是不抛出异常。
RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy(); 
// 丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)不抛出异常
RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardOldestPolicy(); 
// 由调用线程处理该任务,哪来的回哪去,main调用,执行策略让main线程去执行 不抛出异常
RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy(); 

问题:线程是否越多越好?
答:
1、一个计算为主的程序(专业一点称为 CPU密集型程序)。多线程跑的时候,可以充分利用起所有的cpu核心,比如说4个核心的cpu,开4个线程的时候,可以同时跑4个线程的运算任务,此时是最大效率。但是如果线程远远超出cpu核心数量 反而会使得任务效率下降,因为频繁的切换线程也是要消耗时间的。因此对于cpu密集型的任务来说,线程数等于cpu数是最好的了
2、如果是一个磁盘或网络为主的程序IO密集型)。一个线程处在IO等待的时候,另一个线程还可以在CPU里面跑,有时候CPU闲着没事干,所有的线程都在等着IO,这时候他们就是同时的了,而单线程的话此时还是在一个一个等待的。我们都知道IO的速度比起CPU来是慢到令人发指的。所以开多线程,比方说多线程网络传输,多线程往不同的目录写文件,等等。此时 线程数等于IO任务数是最佳的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值