线程池

27 篇文章 0 订阅

为什么要使用线程池?

  1. 创建多线程,系统要处理很多执行时间很短的请求,系统要不断的进行创建和销毁线程,线程池通过重复利用已创建的线程降低创建和销毁带来的消耗,降低资源的消耗。
  2. 当任务到达的时候任务可以不用等待线程创建就直接立即执行,提高的响应速度。
  3. 使用线程池可以统一的进行线程的分配、调度和监控。提高线程的可管理性。

线程池的实现:
ExecutorService:接口 普通调度池
scheduleExecutorService 定时调度池
ThreadPool 创建线程池类对象都是通过这个类来创建

ExecutorService service=new ThreadPoolExecutor(参数);
ExecutorService接口继承Executor接口,ThreadPoolExecutor一共有四个构造方法

public ThreadPoolExecutor(int corePoolSize,//核心线程池大小
                              int maximumPoolSize,//最大线程池大小
                              long keepAliveTime,//存活时间
                              TimeUnit unit,//时间单位
                              BlockingQueue<Runnable> workQueue) {//任务队列
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

ArrayBlockingQueue基于数组的有界队列,固定大小线程池采用它;
LinkedBlockingQueue基于链表的无界队列,吞吐量高于ArrayBlockingQueue,静态工厂方法Excutors.newFixedThreadPool()使用这个队列;
SynchronousQueue不存储元素的无界队列,缓存线程池采用它;(前面的都是按吞吐量从低到高的顺序介绍的)
PriorityBlockingQueue:具有优先级的阻塞队列
ThreadFactory threadFactory
RejectedExecutionHandler handler饱和策略,AbortPolicy–直接抛出异常,CallerRunsPolicy–只用调用者所在线程来执行任务,DiscardOldestPolicy–丢弃队列中最近的一个任务,并执行当前任务,DiscardPolicy不处理丢弃掉。

线程池实现原理
1)线程池判断核心线程池是否都在执行任务,如果不是,则创建一个新的工作线程来执行任务
2)**线程池判断工作队列是否已满,**没有满的话将新提交的任务存储在这个工作队列里,等待调度
3)线程池判断线程池线程是否都处于工作状态,如果没有,就创建一个新的工作线程来执行任务,如果已经满了,就交给饱和策略处理。

ThreadPoolExecutor执行executor方法执行流程如下:
1)当前运行的线程少于核心线程池大小就创建新线程来执行任务(这一步需要获取全局锁)
2)运行的线程大于核心线程池大小或者等于,将任务加入BlockingQueue
3)如果BlockingQueue已满,无法加入队列,就创建新的线程来处理任务(需要获取全局锁)
4)如果创建新线程使当前运行的线程超过最大线程池大小,任务将被拒绝,调用RejectedExecutionHandler.rejectedExcution()方法

ThreadPoolExecutor采用以上步骤的设计是为了在执行executor方法时,尽可能的避免获取全局锁。在ThreadPoolExecutor完成预热后(当前线程数大于等于核心线程数,几乎所有的executor的调用都是执行第二步,第二步不需要获取全局锁)。

工作线程
线程池创建线程时会把线程封装为worker(工作线程),Worker在执行完任务后,还会循环获取工作队列里的任务来执行。
线程池中的执行任务分为两种情况:
1.在executor方法中创建一个线程时,会让这个线程执行当前任务
2.这个线程执行完当前任务后会反复从BlockingQueue获取任务来执行
向线程池提交任务
可以使用两个方法向线程池提交任务,分别为execute()和submit()方法。
executor方法用于提交不需要确认返回值的任务,所以无法判断任务是否被线程池执行成功。
submit()用于提交需要返回值的任务,线程池会返回一个future类型的对象,通过这个future对象可以判断任务是否执行成功,并且可以通过future的get方法获取返回值,get()方法会阻塞当前线程直到任务完成,而使用get(long timeout,TimeUnit unit) 方法会阻塞当前线程一段时间后立即返回,这时候可能任务没有执行完。
关闭线程池
通过调用线程池的shutdown或showdownNow方法来关闭线程池,它们的原理是遍历线程池中的工作线程,逐个调用线程的interrupt方法来中断线程,所以无法响应中断的任务可能永远无法终止,但是存在一定的区别。

线程池工具类:Executors
内置四大线程池:
1)单线程池
2)固定大小线程池 newFixedThreadPool(int nThread)
3)缓存池
4)定时调度池

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值