线程池

作者: 小鱼_a563 | 来源:发表于2022-12-03 14:22 被阅读0次

1.为什么要使用线程池?2.线程池的基本原理是什么?3.怎么学习线程池?
线程池使用了池化技术。池化技术用于我们常见的:数据库连接池,jvm中的常量池,对象池,线程池等等
池化技术:通俗的意思就是将一些我们经常用的资源预先放入一个池子中,后面我们需要使用资源的时候不需要再次创建,使用完毕之后也不需要销毁资源,只需要重新放回到池子中。因为很多大型并且常用的资源创建和销毁都是极具消耗内存和CPU的。
线程池优点

  • 线程池解决了线程的创建销毁的资源浪费的问题 。
  • 便于管理线程。
  • 提高线程的响应速度。

了解线程池的三大方法,七大参数,四种拒绝策略

三大方法

三大方法指的是创建线程池的三种方式(不推荐使用,因为容易导致oom。我们开放一般会使用ThreadPoolExecutor创建线程池)。

  • Executors.newSingleThreadExecutor():使用Executors创建一个线程池,线程池中只有一个线程(结果看下图:SingleThreadExecutor.png)
  • Executors.newCachedThreadPool(): 使用Executors创建一个线程池,遇强则强,遇弱则弱。一个弹性的线程池,jvm会根据提交的任务数自动改变池中的线程数量(结果看下图:CachedThreadPool.png)
  • Executors.newFixedThreadPool(int nThreads):使用Executors创建一个固定大小的线程池,参数是线程个数。(结果看下图:FixedThreadPool.png)
/**
 * @author 小鱼
 * @version 1.0
 * @date 2022/12/3 11:39 上午
 *  三大方法:
 *    1.Executors.newSingleThreadExecutor()
 *      使用Executors创建一个线程池,线程池中只有一个线程
 *    2.Executors.newCachedThreadPool()
 *      使用Executors创建一个线程池,遇强则强,遇弱则弱。一个弹性的线程池,会根据提交的任务数自动改变池中的线程数量
 *    3.Executors.newFixedThreadPool(int nThreads)
 *      使用Executors创建一个固定大小的线程池,参数是线程个数。
 */
public class Demo01 {
  public static void main(String[] args) {
    ExecutorService threadPool = Executors.newSingleThreadExecutor();
//    ExecutorService executorService = Executors.newCachedThreadPool();
//    ExecutorService executorService = Executors.newFixedThreadPool(5);
    try {
      for (int i = 0; i < 10; i++) {
        threadPool.execute(()->{
          System.out.println(Thread.currentThread().getName() + " OK");
        });
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      threadPool.shutdown();
    }
  }
}
SingleThreadExecutor.png
CachedThreadPool.png
FixedThreadPool.png

七大参数

七大参数说的是ThreadPoolExecutor类中的七个参数,重点:核心线程数,拒绝策略
下面也会通过一个银行办理业务的列子详细的介绍这七个参数作用。
上面的三大方法中创建线程池其实内部实现还是调用了ThreadPoolExecutor类。
比如:newFixedThreadPool(int nThreads)方法。

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

下面看一下ThreadPoolExecutor中怎么创建线程池的,并且7个参数有什么含义。

参数名 含义
corePoolSize 池中核心线程数量,也可以理解为保留的数量
maximumPoolSize 池中线程最大的数量
keepAliveTime 当任务超过了核心线程数量,多久超时了之后,开启池中其他空闲线程
unit 超时单位
workQueue 阻塞队列,当提交任务超过核心线程数量时,任务就会放入阻塞队列中
threadFactory 创建线程池,一般使用默认的
handler 拒绝策略,任务数量超过了池子最大处理范围,就会通过拒绝策略进行拒绝任务
  • 最大处理范围:最大线程数量+最大阻塞队列长度
 public class Demo02 {

  public static void main(String[] args) {
    ThreadPoolExecutor threadPoolExecutor = null;
    try {
      threadPoolExecutor = new ThreadPoolExecutor(
          2,
          5,
          3,
          TimeUnit.SECONDS,
          new LinkedBlockingQueue<Runnable>(3),
          Executors.defaultThreadFactory(),
          new ThreadPoolExecutor.AbortPolicy()
      );
      for (int i = 1; i <= 8; i++) {
        threadPoolExecutor.execute(()->{
          System.out.println(Thread.currentThread().getName() + " OK");
        });
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      threadPoolExecutor.shutdown();
    }
  }
}

四大拒绝策略

当任务数量超过线程池中最大处理范围,就会由线程池的拒绝策略处理任务

拒绝策略名称 具体含义
AbortPolicy() 多出的任务直接拒绝处理导致丢失任务),直接抛出异常:java.util.concurrent.RejectedExecutionException
CallerRunsPolicy() 多出来的任务,哪里来的回哪里去,线程池也不处理,不会抛出异常(见图:CallerRunsPolicy.png)
DiscardPolicy() 多出的任务直接拒绝处理,不抛出异常(导致丢失任务)。
DiscardOldestPolicy() 多出的任务池子会去尝试的竞争最早处理任务的线程A,如果最早线程A还在处理任务,就直接拒绝任务。如果线程A没有处理任务,那么线程A会继续执行未处理的任务。不抛出异常。
CallerRunsPolicy.png

银行业务办理列子

下面我们通过一个银行排队处理业务的列子深入理解一下这七大参数

  • 场景:生活中,人们经常去银行办理业务,常见的是银行总共有5个窗口(最大线程数量),3个休息等待区(阻塞队列),一直开放的窗口有2个(核心线程数量),当人比较多的时候,休息区也满了还有人要办理业务的时候另外3个也会开放(任务等待超时了,空闲的线程去处理任务)。人员太多了,业务员处理到加班也处理不完,银行保安可能就告诉后面的人不用排队了,或者直接关门(拒绝策略)


    场景一.png

怎么设置核心和最大的线程数

1.CPU型:cpu有几个线程就设置几个(Runtime.getRuntime().availableProcessors())
2.IO密集型:开放人员知道自己系统有多少个大IO操作任务,然后一般都是根据这个数量*2

相关文章

  • java线程池

    线程VS线程池 普通线程使用 创建线程池 执行任务 执行完毕,释放线程对象 线程池 创建线程池 拿线程池线程去执行...

  • java----线程池

    什么是线程池 为什么要使用线程池 线程池的处理逻辑 如何使用线程池 如何合理配置线程池的大小 结语 什么是线程池 ...

  • Java线程池的使用

    线程类型: 固定线程 cached线程 定时线程 固定线程池使用 cache线程池使用 定时调度线程池使用

  • Spring Boot之ThreadPoolTaskExecut

    初始化线程池 corePoolSize 线程池维护线程的最少数量keepAliveSeconds 线程池维护线程...

  • 线程池

    1.线程池简介 1.1 线程池的概念 线程池就是首先创建一些线程,它们的集合称为线程池。使用线程池可以很好地提高性...

  • 多线程juc线程池

    java_basic juc线程池 创建线程池 handler是线程池拒绝策略 排队策略 线程池状态 RUNNIN...

  • ThreadPoolExecutor线程池原理以及源码分析

    线程池流程: 线程池核心类:ThreadPoolExecutor:普通的线程池ScheduledThreadPoo...

  • 线程池

    线程池 [TOC] 线程池概述 什么是线程池 为什么使用线程池 线程池的优势第一:降低资源消耗。通过重复利用已创建...

  • java 线程池使用和详解

    线程池的使用 构造方法 corePoolSize:线程池维护线程的最少数量 maximumPoolSize:线程池...

  • 线程池

    JDK线程池 为什么要用线程池 线程池为什么这么设计 线程池原理 核心线程是否能被回收 如何回收空闲线程 Tomc...

网友评论

      本文标题:线程池

      本文链接:https://www.haomeiwen.com/subject/vogsfdtx.html