并发编程之:线程池(一)

大家好,我是小黑,一个在互联网苟且偷生的农民工。

池化

线程池是在计算机开发中常见的一种 池化技术,是为了提高资源的利用率,将一些资源重复利用,避免重复的构建来提高效率。类似字符串常量池,数据库连接池,HttpClient连接池等,都是用的池化技术。

线程池

在没有线程池概念之前,我们要使用线程必须先通过创建一个Thread类来完成线程的构建,并调用 start()方法开启,在线程执行完会将线程销毁,而线程资源是很宝贵的,创建和销毁线程会造成资源的浪费。而线程池是将创建的线程存储到一个池中,在需要使用时从池中去拿,使用完之后再讲线程归还到池中,下一次接着使用。

举个栗子,好比我们去银行办理业务时,银行会有窗口为客户办理业务,如果没有线程池,就好比每次来一个客户,银行都打开一个窗口,办理完业务之后将窗口关闭,这样确实很浪费时间,所以银行会默认开几个窗口,比如三个,等客户来办理业务;一个客户办理完,下一个客户可以继续在这个窗口办理。

并发编程之:线程池(一)

核心线程数

在线程池初始化时,会指定创建核心线程的数量,有任务提交给线程池时,先判断是否有空闲线程,如果有空闲线程,则直接使用,如果没有则看当前线程池中的数量是不是小于核心线程数,如果是则创建新的线程,如果已经到达核心线程数,则需要做下一步操作。

等待队列

下一步操作就是要进入等待队列,等待队列好比是去银行办业务时没有空闲窗口,需要坐在大厅的座椅上排队;线程池也是一样,如果没有核心线程,则需要将任务放入等待队列,等待有空闲线程再执行。

最大线程数

那我们都知道银行有时候人特别多的时候,会增加窗口,一般是当大厅的座椅坐满人时,窗口都很紧张处理不过来,这是会增加窗口;线程池也是一样,如果等待的任务已经放满了等待队列,并且核心线程都在繁忙,这时会查看线程池中的线程数量是否到达最大线程数,如果没有则会创建新的线程来继续处理。

并发编程之:线程池(一)

拒绝策略

那如果说,线程池中的线程已经到达最大线程数并且都在繁忙,还有新的任务进来,好比银行已经坐满人了,窗口也都在忙,客户都排到门口了,这时要是还有人要办理,应该怎么处理呢?银行一般会让这个人先回家,改天再来办,或者如果是个大客户,银行可能会单独带去VIP办公室办理等等。线程池在这种情况下也有相应的处理方式,这种处理方式我们称之为 拒绝策略,如果会放任务在当前线程执行,或者直接将任务丢弃等等,在后面的章节中我会详细给大家介绍。

JDK中的线程池

在JDK中提供了相应的API来创建线程池,这些API也是在我们最近讲到过的JUC包中。

并发编程之:线程池(一)

Executor

首先,线程池需要具备能够执行任务的能力,这个任务通过一个线程来处理。而这个执行任务的能力通过 Executor接口来约定。

public interface Executor {
    void execute(Runnable command);
}

ExecutorService

在某些场景我们需要知道任务执行完之后的结果,拿到返回值,而 Runnable接口是没有返回值的;以及一些可以关闭线程池中的线程,执行线程中的任务的方法,定义在 ExecutorService接口中。

并发编程之:线程池(一)

ThreadPoolExecutor

ThreaPoolExecutor则是对 ExecutorService的具体实现类,通过 ThreaPoolExecutor类可以创建出一个线程池,我们先来看一下代码。

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    // 核心线程数 corePoolSize
    3,
    // 最大线程数 maximumPoolSize
    5,
    // 空闲线程保留存活的时间和时间单位
    10, TimeUnit.SECONDS,
    // 等待队列
    new ArrayBlockingQueue<>(3),
    // 创建线程的工厂
    Executors.defaultThreadFactory(),
    // 拒绝策略
    new ThreadPoolExecutor.AbortPolicy()
);

从代码我们可以看出,创建一个线程池,需要指定我们上面说到的核心线程数,最大线程数,等待队列,拒绝策略等,并且还要指定创建线程的工厂对象。

当然ThreadPoolExecutor也有其他的构造方法,可以不显式指定拒绝策略和工厂对象。

new ThreadPoolExecutor(3,5,10,TimeUnit.SECONDS,new ArrayBlockingQueue<>(3));
// 构造方法
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue workQueue) {
    // 使用默认的线程工厂和默认的拒绝策略。
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), defaultHandler);
}

7个线程池参数

  • corePoolSize:核心线程数
  • maximumPoolSize:最大线程数
  • keepAliveTime:空闲线程保持存活时间
  • unit:空闲线程保持存活时间单位
  • workQueue:等待队列
  • threadFactory:线程创建工厂
  • RejectedExecutionHandler:拒绝策略

4种拒绝策略

这里我们说一下4中拒绝策略。接口 RejectedExecutionHandler定义了拒绝策略,所有的拒绝策略都需要实现该接口。

public interface RejectedExecutionHandler {
    void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}

在ThreadPoolExecutor类中定义了4个拒绝策略的具体实现。

  • AbortPolicy:拒绝处理,抛出异常
  • CallerRunsPolicy:由创建该线程的线程(main)执行
  • DiscardPolicy: 丢弃,不抛出异常
  • DiscardOldestPolicy:和最早创建的线程进行竞争,不抛出异常

可通过如下方式进行拒绝策略的创建。

// 拒绝处理,抛出异常
new ThreadPoolExecutor.AbortPolicy();
// 由创建该线程的线程(main)执行
new ThreadPoolExecutor.CallerRunsPolicy();
// 丢弃,不抛出异常
new ThreadPoolExecutor.DiscardPolicy();
// 和最早创建的线程进行竞争,不抛出异常
new ThreadPoolExecutor.DiscardOldestPolicy();

4种线程池种类

那么具体我们在使用时应该创建怎样的线程池呢?在JDK的 Executors工具类为我们提供了4种线程池的创建方式。

// 只有一个线程
Executors.newSingleThreadExecutor();
// 固定线程数
Executors.newFixedThreadPool(5);
// 可伸缩的
Executors.newCachedThreadPool();
// 可延迟执行,使用优先队列DelayedWorkQueue
Executors.newScheduledThreadPool(3);

小结

好的,通过今天的内容我们先对线程池的使用有一个初步的了解,下期内容再跟大家深入解析一下线程池中的具体实现原理。

本期内容就到这里,我们下期见。
关注公众号【小黑说Java】干货不断。

并发编程之:线程池(一)

Original: https://www.cnblogs.com/heiz123/p/15225361.html
Author: 小黑说Java
Title: 并发编程之:线程池(一)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/580210/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • MyBatis保姆级理解与使用,动态SQL(核心)

    动态S QL(核心) 1.1 简介 Mybatis 框架的动态SQL 技术是一种根据特定条件动态拼装SQL 语句的功能,它存在的意义是为了解决拼接SQL 语句字符串时的难点问题。 …

    Java 2023年6月16日
    051
  • IO(递归)

    递归:方法定义中调用方法本身的现象 注意事项:* A:递归一定要有出口,否则就是死递归* B:递归的次数不能太多,否则就内存溢出* C:构造方法不能递归使用 阶乘案例 不死神兔案例…

    Java 2023年6月5日
    080
  • 给定class对象返回该类的实例

    今天分享给大家一个实用的开发技巧, 创建一个返回值为泛型的对象构建函数, 要求是传入返回值类的 class 对象. 例如: 平时我们开发接口的时候发现很多响应类里面基本都会有cod…

    Java 2023年6月7日
    089
  • java的classpath指定

    java的”一次编译,到处运行”的原理是,把源文件编译成字节码,字节码由java虚拟机执行,然后只需要在各个平台安装对应的java虚拟机就可以了。 举个例子…

    Java 2023年5月29日
    073
  • 头歌计组实践

    头歌计组实践 一.关于用什么写Verilog Verilog是个硬件描述语言,不像高级语言用户群体那么大,所以好像没有像什么IDE那样的东西,个人目前了解有以下这么几个形式: 文本…

    Java 2023年6月7日
    083
  • beanFactory 设计模式 Bean 生命周期的胡言乱语,哈哈

    写在前面的话 适用读者:有一定经验的,本文不适合初学者,因为可能不能理解我在说什么 文章思路:不会一开始就像别的博客文章那样,Bean 的生命周期,源码解读(给你贴一大堆的源码)。…

    Java 2023年6月5日
    068
  • Java如何仅将字符串中的数字部分转成数字类型

    需要将字符串中的数字部分转成数字类型,看到网上很多都是利用Integer.parseInt(string)用过循环的方式来判断单个字符能否转换成功再进行拼接转换 其实可以使用Str…

    Java 2023年6月7日
    080
  • 1438. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit

    题目: Given an array of integers nums and an integer limit, return the size of the longest n…

    Java 2023年5月29日
    075
  • 力扣算法题9. 回文数(Java)

    力扣算法题9. 回文数(Java) 给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 回文数是指正序(从左向右)和倒序(从右向左)读都是一…

    Java 2023年6月7日
    076
  • entitybuilder–一个简单的业务通用框架

    关于业务通用框架的思考 业务系统是千差万别的,例如,保存、更新和删除订单,或者保存订单和保存客户,走的根本不是一个流程。但是,它们还是有共同点,它们的流程大致可以分成下面的几个部分…

    Java 2023年6月13日
    068
  • 顺序结构(Java)

    基本介绍 Java的基本结构就是顺序结构,除非特别指明,否则就按照顺序一字一句执行 顺序结构是最简单的算法结构 语句与语句之间,框与框之间是按照从上到下的顺序进行,它是由若干个依次…

    Java 2023年6月9日
    064
  • 狂神说笔记——SpringBoot开发单体应用21

    Spring Boot 开发单体应用2 6.配置环境及首页 新建spring boot项目,导入依赖包。 <project xmlns="http://maven….

    Java 2023年5月30日
    072
  • SQL语句的整合

    基础语法 https://blog.csdn.net/m0_37989980/article/details/103413942 CRUD 提供给数据库管理员的基本操作,CRUD(…

    Java 2023年6月16日
    0103
  • MQ 问题详解

    MQ 优缺点以及对应的解决方案 posted @2021-09-01 14:56 FrankYou 阅读(70 ) 评论() 编辑 Original: https://www.cn…

    Java 2023年5月30日
    073
  • eclipse快捷键大全

    eclipse快捷键大全 /* * Eclipse&#x4E2D;&#x7684;&#x5FEB;&#x6377;&#x952E;&…

    Java 2023年6月6日
    087
  • SpringMVC完整学习!!!

    1.楔子 1.1、了解MVC 1.2、MVC框架的主要功能 2.初识SpringMVC 2.1、为什么要学习SpringMVC 2.2、了解SpringMVC 3.入门项目初体验!…

    Java 2023年6月8日
    0167
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球