一、线程池的概念

“池”,就是一个工厂,会提前生产出一些东西供使用。所以线程池就是处理多线程的一种方式。
其作用就在于:复用已有资源,控制资源总量

二、为什么使用线程池

如果不使用线程池,那么:
(1)使用单线程,但是这种方式吞吐量非常低,且请求量一大效率就会显得非常低。
(2)那如果对于每个请求都开一个线程去处理,这样一旦请求量过大的时候,线程的创建和销毁都要花费时间,并且线程本身也要占用一定的内存。

使用线程池后,既可以解决单线程低吞吐量和响应慢的问题,又解决了为每一个请求创建线程所耗费的资源问题。

线程池通过限制线程的数量,可以使线程数维持在一个合理的数量,充分发挥了CPU的作用。

而且,线程池遵循了生产者消费者模式,将任务的创建和执行解耦

三、ThreadPoolExecutor

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

这里是ThreadPoolExecutor最重要的一个构造方法
(1)corePoolSize : 线程池中维护线程的最少数量
当线程数少于corePoolSize时,就创建一条新的任务,不管是否有空闲的线程。

(2)maximumPoolSize: 线程池中维护线程的最大数量
当线程数到达corePoolSize,并且都不空闲,那么新任务都放到任务队列中去。当任务队列放满之后,如果线程数小于maximumPoolSize,就继续创建新线程。

(3)keepAliveTime:线程池维护线程所允许的空闲时间
如果线程空闲的时间超过keepAliveTime,那么就撤销它。

(4)unit: 线程池维护线程所允许的空闲时间的单位

(5)workQueue: 线程池所使用的缓冲队列
一般采用阻塞队列,有很多种:
无界阻塞队列、有界阻塞队列、同步移交队列

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

四、四种线程池

1、CachedThreadPool
先查看有没有可用的线程,没有再创建新线程

2、FixedThreadPool
与上一种差不多,但是不允许随时创建新线程
任意时间点,最多只能有固定数目的活动线程存在,此时如果有新的线程要建立,只能放在另外的队列中等待,直到当前的线程中某个线程终止直接被移出池子。

3、ScheduledThreadPool
这个池子里的线程可以按 schedule 依次 delay 执行,或周期执行

4、SingleThreadExecutor
任意时间内池子里只能有一个线程。


hushucheng
42 声望2 粉丝