并发编程-线程池

小灰灰 2023-02-28 11:22 173阅读 0赞

文章目录

  • 线程池
    • 线程池原理
    • 线程池分类

线程池

为什么需要使用线程池?

  • 线程的创建和销毁都需要消耗系统资源,线程池可以复用已有的线程
  • 线程也是对象,线程池可以复用线程对象,减低内存消耗
  • 可以控制并发数量,并发数量过多,可能会导致资源消耗过多
  • 可以对线程进行统一管理

线程池原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SmBclC3n-1595301423983)(https://raw.githubusercontent.com/chenxiao19920206/RedSpiderArticlePhotos/master/java-base/multi-thread/%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%B8%BB%E8%A6%81%E7%9A%84%E5%A4%84%E7%90%86%E6%B5%81%E7%A8%8B.png)\]

  • 线程池线程数量 < 核心线程数,每次都会创建新的线程去处理任务
  • 线程数量 == 核心线程数,则每次新加的任务都会添加到任务队列,线程会去任务队列取任务执行(体现线程复用)
  • 当任务队列满了 && 线程数 < 最大线程数,则会创建救急线程去执行,执行完会被销毁
  • 如果任务队列满了 && 线程数 = 最大线程数,则会执行拒绝策略

拒绝策略:

  • 默认是抛出异常,ThreadPoolExecutor.AbortPolicy:默认拒绝处理策略,丢弃任务并抛出RejectedExecutionException异常。
  • ThreadPoolExecutor.DiscardPolicy:丢弃新来的任务,但是不抛出异常。
  • ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列头部(最旧的)的任务,然后重新尝试执行程序(如果再次失败,重复此过程)。
  • ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务。

shutdown和shutdownNow

  • shutdown方法后处于SHUTDOWN,线程池不接受新的任务,等待任务队列中的任务执行完成
  • shutdownNow方法后处于STOP,线程池不接受新任务,并且在执行中的任务也不执行完强制退出

线程池分类

newCachedThreadPool

  1. public static ExecutorService newCachedThreadPool() {
  2. return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
  3. 60L, TimeUnit.SECONDS,
  4. new SynchronousQueue<Runnable>());
  5. }
  • 每个线程都是救急线程,使用完会60s空闲后会被回收掉,采用synchronousQueue,每进来一个任务就会有一个线程去取,任务队列不保存任务
  • 当需要执行很多短时间的任务时,CacheThreadPool的线程复用率比较高, 会显著的提高性能。而且线程60s后会回收,意味着即使没有任务进来,CacheThreadPool并不会占用很多资源。

newFixedThreadPool

  1. public static ExecutorService newFixedThreadPool(int nThreads) {
  2. return new ThreadPoolExecutor(nThreads, nThreads,
  3. 0L, TimeUnit.MILLISECONDS,
  4. new LinkedBlockingQueue<Runnable>());
  5. }
  • 核心线程数 = 最大线程数,只能创建核心线程,不能创建非核心线程。因为LinkedBlockingQueue的默认大小是Integer.MAX_VALUE,故如果核心线程空闲,则交给核心线程处理;如果核心线程不空闲,则入列等待,直到核心线程空闲
  • 由于线程不会被回收,会一直卡在阻塞,所以没有任务的情况下, FixedThreadPool占用资源更多。
    都几乎不会触发拒绝策略,但是原理不同。FixedThreadPool是因为阻塞队列可以很大(最大为Integer最大值),故几乎不会触发拒绝策略;CachedThreadPool是因为线程池很大(最大为Integer最大值),几乎不会导致线程数量大于最大线程数,故几乎不会触发拒绝策略。

newSingleThreadExecutor

  1. public static ExecutorService newSingleThreadExecutor() {
  2. return new FinalizableDelegatedExecutorService
  3. (new ThreadPoolExecutor(1, 1,
  4. 0L, TimeUnit.MILLISECONDS,
  5. new LinkedBlockingQueue<Runnable>()));
  6. }
  • 单线程线程池,如果这个唯一的线程不空闲,那么新来的任务会存储在任务队列里等待执行。
    newScheduledThreadPool

    public ScheduledThreadPoolExecutor(int corePoolSize) {

    1. super(corePoolSize, Integer.MAX_VALUE,
    2. DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
    3. new DelayedWorkQueue());

    }

  • 定时任务线程池

发表评论

表情:
评论列表 (有 0 条评论,173人围观)

还没有评论,来说两句吧...

相关阅读

    相关 并发编程-线

    文章目录 线程池 线程池原理 线程池分类 线程池 为什么需要使用线程池? 线程的创建和销毁都需要消耗系统资源,线程池可以复

    相关 并发编程线线

    1. 线程 线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。 线程是调度CPU资源的最小单位,线程模型分为K

    相关 并发编程线

    为什么使用线程池 有时候,系统需要处理非常多的执行时间很短的请求,如果每一个请求都开启一个新线程的话,系统就要不断的进行线程的创建和销毁,有时花在创建和销毁线程上的时间会