Java线程池理解

1. ThreadPoolExecutor构造方法

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

2. 参数解释

1. corePoolSize:核心池的大小。

在创建了线程池后,默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中;如果调用了prestartAllCoreThreads()或者prestartCoreThread()方法,则在没有任务到来之前预创建corePoolSize个线程或者一个线程。

2.maximumPoolSize:

线程池最大线程数,它表示在线程池中最多能创建多少个线程;当核心池的线程以及缓存队列中的线程满了以后,新创建的线程就会使用备用线程,备用线程数等于最大线程减去核心线程数。

3.keepAliveTime:

表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize,即此参数只对备用线程发挥作用。但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0。

4.TimeUnit:

参数keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性:

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

5.BlockingQueue:

workQueue:一个阻塞队列,用来存储等待执行的任务,即缓存队列,当核心线程都被占用时,新创建的线程进入阻塞队列排队等待。阻塞队列一共三种类型:

ArrayBlockingQueue;
LinkedBlockingQueue;
SynchronousQueue;
  1. ArrayBlockingQueue:ArrayBlockingQueue:有界队列。可以限定队列的长度,接收到任务的时候,如果没有达到corePoolSize的值,则新建线程(核心线程)执行任务,如果达到了,则入队等候,如果队列已满,则新建线程(非核心线程)执行任务,又如果总线程数到了maximumPoolSize,并且队列也满了,则发生错误。
  2. LinkedBlockingQueue:无界队列。这个队列接收到任务的时候,如果当前线程数小于核心线程数,则新建线程(核心线程)处理任务;如果当前线程数等于核心线程数,则进入队列等待。由于这个队列没有最大值限制,即所有超过核心线程数的任务都将被添加到队列中,这也就导致了maximumPoolSize的设定失效,因为总线程数永远不会超过corePoolSize。
  3. SynchronousQueue:这个队列接收到任务的时候,会直接提交给线程处理,而不保留它,如果所有线程都在工作怎么办?那就新建一个线程来处理这个任务!所以为了保证不出现<线程数达到了maximumPoolSize而不能新建线程>的错误,使用这个类型队列的时候,maximumPoolSize一般指定成Integer.MAX_VALUE,即无限大。

6.ThreadFactory:

线程工厂,用来创建线程

7.RejectedExecutionHandler:

拒绝策略,表示任务添加失败后如何处理该任务,当提交任务数超过maxmumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler来处理。

  1. AbortPolicy
    默认。直接抛异常。
  2. CallerRunsPolicy
    只用调用者所在的线程执行任务,重试添加当前的任务,它会自动重复调用execute()方法
  3. DiscardOldestPolicy
    丢弃任务队列中最久的任务。
  4. DiscardPolicy
    丢弃当前任务。
    在这里插入图片描述

3.执行流程

在这里插入图片描述任务进来时,首先执行判断,判断核心线程是否处于空闲状态,如果不是,核心线程就先就执行任务,如果核心线程已满,则判断任务队列是否有地方存放该任务,若果有,就将任务保存在任务队列中,等待执行,如果满了,在判断最大可容纳的线程数,如果没有超出这个数量,就开创非核心线程执行任务,如果超出了,就调用handler实现拒绝策略。

4. 提交任务

  1. Callable
    该类任务有返回结果,可以抛出异常。
    通过submit()方法提交,返回Future对象。
    可通过get获取执行结果。
  2. Runnable
    该类任务只执行,无法获取返回结果,并在执行过程中无法抛异常。 通过execute()提交。

5. 关闭线程池

关闭线程池有两种方式:shutdown和shutdownNow,关闭时,会遍历所有的线程,调用它们的interrupt函数中断线程。但这两种方式对于正在执行的线程处理方式不同。

  1. shutdown()
    仅停止阻塞队列中等待的线程,那些正在执行的线程就会让他们执行结束。
  2. shutdownNow()
    不仅会停止阻塞队列中的线程,而且会停止正在执行的线程。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值