线程池

82 阅读2分钟

1.线程池

使用享元模式 从池子里面获取对象,没有就创建,比较动态,节约资源。

列如 jdbc连接池

jdk创建线程池几种方式

ExecutorService executorService1 = Executors.newCachedThreadPool();//可缓存线程池
executorService1.execute(new Runnable() {
    @Override
    public void run() {
        System.out.println();
    }
});

ExecutorService executorService2 = Executors.newSingleThreadExecutor();//单例线程池
ExecutorService executorService3 = Executors.newFixedThreadPool(1);//指定数量线程池
ScheduledExecutorService executorService4 = Executors.newScheduledThreadPool(10);//可定时
executorService4.schedule(()->{},1L, TimeUnit.SECONDS);

底层都是使用:new ThreadPoolExecutor()

image.png

线程池七大参数

public ThreadPoolExecutor(int corePoolSize,                       //核心线程大小
                              int maximumPoolSize,                //线程池最大线程数量
                              long keepAliveTime,                 //多余的空闲线程存活时间
                              TimeUnit unit,                      //空闲线程存活时间单位
                              BlockingQueue<Runnable> workQueue,  //工作队列
                              ThreadFactory threadFactory,        //线程工厂
                              RejectedExecutionHandler handler)   //拒绝策略

AbortPolicy:丢弃任务并抛出 RejectedExecutionException 异常。(默认这种)

DiscardPolicy:丢弃任务,但是不抛出异常

DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程) 。也就是当任务被拒绝添加时,会抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务从队尾添加进去,等待执行。

CallerRunsPolicy:谁调用,谁处理。由调用线程(即提交任务给线程池的线程)处理该任务,如果线程池已经被shutdown则直接丢弃 同步方式运行

线程池原理:

1.线程池准备好,core核心线程开始接受任务;

2.当core核心线程满了之后,再有任务进来就会放入阻塞队列里面,空闲的核心线程就会去阻塞队列里面获取任务执行;

3.当阻塞队列满了之后就会生成新的线程,最大达到maximumPoolSize;

4.超过核心线程的空闲线程会在keepAliveTime时间周期内被销毁掉,最终保留corePoolSize线程数量。

5.如果达到最大线程maximumPoolSize数量还有任务,就会执行拒绝策略。

不建议使用jdk自带的创建线程池方法,一般自行构造。

1.workQueue工作队列使用无界队列(没有设置固定大小的队列),容易内存泄漏 image.png

2.最大线程为Integer.MAX_VALUE,无限创建线程 image.png