java线程池《常见创建方式和基本参数介绍》

335 阅读3分钟

一:为什么使用线程池

1.1:降低资源的消耗

通过重复利用已经创建好的线程降低线程的创建和销毁带来的损耗

1.2:提高响应速度

因为线程池中的线程数没有超过线程池的最大上限时,有的线程处于等待分配任务的状态,当任务来时无需创建新的线程就能执行异步任务

1.3:提高线程的可管理性

线程池会根据当前系统特点对池内的线程进行优化处理,减少创建和销毁线程带来的系统开销。无限的创建和销毁线程不仅消耗系统资源,还降低系统的稳定性,使用线程池进行统一分配

二:使用ThreadPoolExecutor创建线程池

image.png

使用ThreadPoolExecutor创建线程池之前,我们首先看这七大参数的含义

  • corePoolSize:核心线程数,线程池创建好以后就准备就绪执行任务
  • maximumPoolSize:线程池最大线程数量,控制线程资源
  • keepAliveTime:存活时间,如果当前线程数量大于corePoolSize数量,当线程空闲时间大于指定的keepAliveTime,就会释放空闲的线程(maximumPoolSize-corePoolSize)
  • TimeUnit:时间单位,小时,分钟,秒等
  • workQueue:阻塞队列,如果有很多任务,就会将目前多于的任务放到阻塞队列中,只要有线程空闲,就会去队列里面取出新的任务继续执行。
  • threadFactory:线程的创建工厂
  • handler:如果队列满了,按照我们指定的拒绝策略拒绝执行任务

2.1ThreadPoolExecutor线程创建

    ThreadPoolExecutor pool=new ThreadPoolExecutor(5,
            100,10, TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(100),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());

}

阻塞队列: image.png 拒绝策略: image.png

2.2工作顺序

  • 1:线程池创建,准备好core数量的核心线程,准备接收任务
  • 2:core满了,就将再进来的任务放入阻塞队列中,空闲的core就会自己去阻塞队列获取任务执行
  • 3:阻塞队列满了,就直接开新线程执行,最大只能开到max指定的数量
  • 4:max满了就会拒绝任务(RejectedExecutionHandler)
  • 5:max都执行完成,此时会有很多空闲线程,在指定的时间keepAliveTime以后,会释放(max-core)个线程

2.3具体示例

例如: 一个线程池,core=20,max=50,queue=100,此时有200并发,线程池如何分配

描述: 因为core=20,此时会有20个立刻得到执行,100个会进去队列queue,再开max-core=30个线程来执行任务,剩下的50个就会使用拒绝策略

三:使用Executors创建线程池

使用Executors创建线程池主要是这四种线程池

3.1newFixedThreadPool

ExecutorService executorServicePool= Executors.newFixedThreadPool(10);

创建一个定长的线程池,可控制线程最大并发数,超出的线程会在队列中等待

3.2newCachedThreadPool

ExecutorService executorServicePool= Executors.newCachedThreadPool();

创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则创建新线程

3.3newScheduledThreadPool

ExecutorService executorServicePool= Executors.newScheduledThreadPool(10);

创建一个定长线程池,支持定时以及周期性任务执行

3.4newSingleThreadExecutor

ExecutorService executorServicePool= Executors.newSingleThreadExecutor();

创建一个单线程的线程池,它只会用唯一的工作线程来执行任务,任务挨个执行。