线程池原理常用四大线程池及七大参数

article/2025/9/14 17:03:26

目录

  • 前言
  • 常用的四种线程池
    • newCachedThreadPool——可缓存线程池
    • newFixedThreadPool————指定线程数量
    • newSingleThreadExecutor————单线程的Executor
    • newScheduleThreadPool——定时线程池
  • 线程池七大参数
    • corePoolSize——核心线程最大数
    • maximumPoolSize——线程池最大线程数
    • keepAliveTime——空闲线程存活时间。
    • unit——空闲线程存活时间单位
    • workQueue——等待队列
    • threadFactory
    • handler——拒绝策略
  • 线程池工作流程

前言

最近在面试,关于一些多线程的内容,细致的部分很容易就想不起来具体应该怎么回答。翻开之前的笔记本,感觉就在眼前,知识不去实践,就像是别人的。尤其是程序猿这行,源源不断的新技术,就不要做捡了芝麻丢了西瓜的人。
总结在博客上,也能再温习一下。用不用的先门清~

常用的四种线程池

newCachedThreadPool——可缓存线程池

描述:

  • 如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

特点

  • 线程的创建数量几乎没有限制。这样可灵活的往线程池中添加线程。
  • 如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程
  • 要注意控制任务的数量,否则,由于大量线程同时运行,很有会造成系统瘫痪。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class executor {public static void main(String[] args) {ExecutorService pool = Executors.newCachedThreadPool();for (int i = 0; i < 10; i++) {final int index = i;try {Thread.sleep(index*1000);} catch (InterruptedException e) {e.printStackTrace();}pool.execute(new Runnable() {public void run() {System.out.println(index);}});}}
}

在这里插入图片描述

newFixedThreadPool————指定线程数量

描述:

  • 创建一个指定工作线程数量的线程池。
  • 每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。

优点:

  • 提高程序效率和节省创建线程时所耗的开销

缺点:

  • 线程池空闲时,即线程池中没有可运行任务时,它不会释放工作线程,还会占用一定的系统资源
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class fixedThreadPool {public volatile int i;public static void main(String[] args) {ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);  for (int i = 0; i < 10; i++) {final int index = i;fixedThreadPool.execute(new Runnable() {public void run() {try {System.out.println(index);Thread.sleep(8000);} catch (Exception e) {e.printStackTrace();}}});}}
}

运行结果:两个线程一起执行,隔8s切换
在这里插入图片描述

newSingleThreadExecutor————单线程的Executor

描述:

  • 只创建唯一的线程来执行任务。保证任务按照指定顺序(FIFO,LIFO,优先级)执行。
  • 如果这个线程异常结束,会有另一个取代它
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class singleThreadExecutor {public static void main(String[] args) {ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();for (int i = 0; i < 10; i++) {final int index = i;singleThreadExecutor.execute(new Runnable() {public void run() {try {System.out.println(index);Thread.sleep(8000);} catch (InterruptedException e) {e.printStackTrace();}}});}}
}

运行:单线程运行
在这里插入图片描述

newScheduleThreadPool——定时线程池

描述:

  • 支持定时及周期性任务执行。

栗子:

  • 延迟3s执行示例代码
import java.sql.Time;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;public class scheduledThreadPool {public static void main(String[] args) {ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);scheduledThreadPool.schedule(new Runnable() {public void run() {System.out.println("延迟5秒执行");}},5, TimeUnit.SECONDS);}
}

在这里插入图片描述

栗子:

  • 延迟2秒后每5秒执行一次,定期执行示例代码
import java.sql.Time;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;public class scheduledThreadPool {public static void main(String[] args) {ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);scheduledThreadPool.scheduleAtFixedRate(new Runnable() {public void run() {System.out.println("延迟5秒执行");}},2,5,TimeUnit.SECONDS);}
}

运行:
在这里插入图片描述

线程池七大参数

corePoolSize——核心线程最大数

maximumPoolSize——线程池最大线程数

keepAliveTime——空闲线程存活时间。

  • 当一个非核心线程被创建,使用完归还给线程池
  • 一个线程如果处于空闲状态,并且当前的线程数量大于corePoolSize,那么在指定时间后,这个空闲线程会被销毁,这里的指定时间由
    keepAliveTime来设定

unit——空闲线程存活时间单位

  • 这是keepAliveTime的计量单位

workQueue——等待队列

  • 当线程池满了,线程就会放入这个队列中。任务调度再取出

jdk提供四种工作队列

  1. ArrayBlockingQueue——基于数组的阻塞队列,按FIFO,新任务放队尾
    • 有界的数组可以防止资源耗尽问题。
    • 当线程池中线程数量达到corePoolSize后,再有新任务进来,则会将任务放入该队列的队尾,等待被调度。
    • 如果队列已经是满的,则创建一个新线程,
    • 如果线程数量已经达到maxPoolSize,则会执行拒绝策略
  2. LinkedBlockingQuene——基于链表的无界阻塞队列,按照FIFO排序
    • 其实最大容量为Interger.MAX
    • 由于该队列的近似无界性,当线程池中线程数量达到corePoolSize后,再有新任务进来,会一直存入该队列,而不会去创建新线程直到maxPoolSize,
    • 因此使用该工作队列时,参数maxPoolSize其实是不起作用的
  3. SynchronousQuene——不缓存任务的阻塞队列
    • 生产者放入一个任务必须等到消费者取出这个任务。
    • 也就是说新任务进来时,不会缓存,而是直接被调度执行该任务,
    • 如果没有可用线程,则创建新线程,如果线程数量达到maxPoolSize,则执行拒绝策略
  4. PriorityBlockingQueue——具有优先级的无界阻塞队列
    • 优先级通过参数Comparator实现。

threadFactory

  • 创建一个新线程时使用的工厂,可以用来设定线程名、是否为daemon线程等等

handler——拒绝策略

当工作队列中的任务已到达最大限制,并且线程池中的线程数量也达到最大限制,这时如果有新任务提交进来,就用到拒绝策略
jdk中提供了4中拒绝策略

  1. CallerRunsPolicy——主线程自己执行该任务
    • 该策略下,在调用者线程中直接执行被拒绝任务的run方法,除非线程池已经shutdown,否则直接抛弃任务。
  2. AbortPolicy——抛出异常
    • 该策略下,直接丢弃任务,并抛出RejectedExecutionException异常
  3. DiscardPolicy——直接丢弃
    • 该策略下,直接丢弃任务,什么都不做
  4. DiscardOldestPolicy——早删晚进
    • 该策略下,抛弃进入队列最早的那个任务,然后尝试把这次拒绝的任务放入队列

线程池工作流程

  • 线程池刚创建时,里面没有一个线程。任务队列是作为参数传进来的。不过,就算队列里面有任务,线程池也不会马上执行它们。
  • 调用 execute() 方法添加一个任务时,线程池会做如下判断:
    • 如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务;
    • 如果正在运行的线程数量大于或等于 corePoolSize,那么将这个任务放入队列;
    • 如果这时候队列满了,而且正在运行的线程数量小于 maximumPoolSize,那么还是要创建非核心线程立刻运行这个任务;
    • 如果队列满了,而且正在运行的线程数量等于 maximumPoolSize,那么线程池会抛出异常 RejectExecutionException。
  • 当一个线程完成任务时,它会从队列中取下一个任务来执行。
  • 当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于 corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到 corePoolSize 的大小。

在这里插入图片描述


http://chatgpt.dhexx.cn/article/YKfgCDPj.shtml

相关文章

创建线程池的七种方式

在 Java 语言中&#xff0c;并发编程往往都是通过床架线程池来实现的&#xff0c;而线程池的创建方式也有很多种&#xff0c;每种线程池的创建方式都对应了不同的使用场景。总结来说线程池的创建可以分为两大类&#xff1a; 通过 Executors 创建 通过 ThreadPoolExecutor 创建…

Java中常用的四种线程池

在Java中使用线程池&#xff0c;可以用ThreadPoolExecutor的构造函数直接创建出线程池实例&#xff0c;在Executors类中&#xff0c;为我们提供了常用线程池的创建方法。 ​ 接下来我们就来了解常用的四种&#xff1a; newFixedThreadPool 首先&#xff0c;看一下这种线程池的…

5种常用的线程池

目录 0 概述1 newCachedThreadPool&#xff08;可缓存的线程池&#xff09;2 newFixedThreadPool&#xff08;固定大小的线程池&#xff09;3 newScheduledThreadPool&#xff08;可做任务调度的线程池&#xff09;4 newSingleThreadPool&#xff08;单个线程的线程池&#xff…

java中的线程池有哪些,分别有什么作用?

阅读完本篇文章会知道如下三点&#xff1a; 1.进程-线程简单介绍 2.java的线程池是什么&#xff0c;有哪些类型&#xff0c;作用分别是什么 3.使用线程池的优点 1.进程-线程的简单介绍 进程 什么是进程呢&#xff1f; 进程是计算机中的程序关于某数据集合的一次运行活动&…

线程池有几种创建方式?

总体来说线程池的创建可以分为以下两类&#xff1a; 通过 ThreadPoolExecutor 手动创建线程池通过 Executors 执行器自动创建线程池。 而以上两类创建线程池的方式&#xff0c;又有 7 种具体实现方法&#xff0c;这 7 种实现方法分别是&#xff1a; Executors.newFixedThre…

创建线程池有哪几种方式

通常开发者都是利用Executors提供的通用线程池创建方法&#xff0c;去创建不同配置的线程池&#xff0c;主要区别在于不同的 Executors目前提供了5种不同的线程池创建配置&#xff1a; 1、newCachedThreadPool&#xff08;&#xff09;&#xff0c;它是用来处理大量短时间工作…

Java常见的5种线程池

在开发过程中我们常常需要使用到多线程来提高我们代码处理某些任务的效率&#xff0c;最基本的两种创建多线程的方式分别是继承Thread类和实现Runnable接口。但是创建线程和销毁线程的系统开销比较大&#xff0c;而且过多的线程会占用过多的内存等资源。在《阿里巴巴Java开发手…

4种常用线程池介绍

一. 线程池简介 1. 线程池的概念&#xff1a; 线程池就是首先创建一些线程&#xff0c;它们的集合称为线程池。使用线程池可以很好地提高性能&#xff0c;线程池在系统启动时即创建大量空闲的线程&#xff0c;程序将一个任务传给线程池&#xff0c;线程池就会启动一条线程来执…

面试突击:线程池有几种创建方式?推荐使用哪种?

在 Java 语言中&#xff0c;并发编程都是通过创建线程池来实现的&#xff0c;而线程池的创建方式也有很多种&#xff0c;每种线程池的创建方式都对应了不同的使用场景&#xff0c;总体来说线程池的创建可以分为以下两类&#xff1a; 通过 ThreadPoolExecutor 手动创建线程池。…

线程池的分类(5种)

Java面试高频提问点 问题一&#xff1a;线程池的创建方式 文章目录 Java面试高频提问点前言一、线程池的分类1.newCachedThreadPool2.newFixedThreadPool3.newSingleThreadExecutor4.newScheduleThreadPool5.newSingleThreadScheduledExecutor 总结 前言 近期因为上海疫情原因…

docker搭建pxc

1、设置阿里云加速器 先搭建一个加速器为后面下载镜像做准备 2、下载pxc镜像 docker pull percona/percona-xtradb-cluster:5.7.21 #下载镜像 docker tag percona/percona-xtradb-cluster:5.7.21 pxc #改镜像名 docker rmi percona/percona…

mysql bootstrap pxc_MYSQL PXC

下载ssl101的安装包上传服务器对应安装目录/usr/local 目录。 [rootlocalhost ~]# yum -y install openssl openssl-devel perl-Time-HiRes perl-DBD-MySQL.x86_64 perl-IO-Socket-SSL.noarch [rootpxc2 ~]# rpm -ivh libev-4.15-1.el6.rf.x86_64.rpm warning: libev-4.15…

mysql pxc集群介绍_PXC集群的概述及搭建

PXC集群的概述及搭建 PXC集群的简介 Percona XtraDB Cluster(下文简称PXC集群)提供了MySQL高可用的一种实现方法。PXC集群以节点组成(推荐至少3节点&#xff0c;便于故障恢复&#xff0c;后面会讨论两节点的情况)&#xff0c;每个节点都是基于常规的 MySQL/Percona Server&…

pxc 数据库

一 首先 拉取pxc镜像 docker pull percona/percona-xtradb-cluster 重命名pxc名字 docker tag percona/percona-xtradb-cluster pxc 删除之前的 docker rmi percona/percona-xtradb-cluster 二 创建内部网络 docker network create --subnet172.18.0.0/24 net1 查看net1网…

MySQL_PXC集群_综合应用

MySQL_PXC集群_综合应用 简述部署PXC集群和主从区别综合应用部署PXC集群部署主从复制集群MasterSlave 部署MyCat节点一节点二 部署HAProxy 简述 Percona XtraDB Cluster&#xff08;简称PXC&#xff09;是针对MySQL用户的高可用性和扩展性解决方案&#xff0c;基于Percona Ser…

mysql pxc 使用_PXC使用介绍

用户发起Commit&#xff0c;在收到Ok之前 集群每次发起一个动作&#xff0c;都会有一个唯一的编号 PXC独有的Global Trx Id 动作发起者: commit_cb其它节点多了一个动作&#xff1a; apply_cb 上面的这些动作&#xff0c;是通过那个端号交互的&#xff1f;4567 4568端口 IST 只…

docker搭建pxc集群

因为公司需要搭建mysql集群&#xff0c;本来使用原生的mysql镜像搭建了一个简单的主从集群&#xff0c;后来发现使用pxc集群更加方便快捷&#xff0c;而且数据同步性能更强&#xff0c;所以尝试搭建一个pxc集群。 1.pxc介绍 Percona XtraDB Cluster&#xff08;PXC集群&#…

mysql gtid 还是pxc_PXC中的GTIDs

基本环境&#xff1a;PXC 5.7.19 RowGtid&#xff0c;3节点 一、Galera GTID vs MySQL GTID 1.1、Galera GTID vs MySQL GTID Both kinds of GTIDs are using the same format: . For Galera, is generated when the cluster is bootstrapped. This is shared by all nodes. Fo…

mysql pxc搭建_MySQL(PXC)集群搭建

前言 我这里使用三台CentOS Linux release 7.8.2003的虚拟机来作演示 [rootn1 ~]# cat /etc/redhat-release CentOS Linux release 7.8.2003 (Core) 安装前准备 请确保服务器没有安装MySQL&#xff0c;如果已经安装了请先卸载(后面会起冲突) 删除 MariaDB 这里我的服务器版本为…

docker pxc mysql_docker安装pxc集群的详细教程

前言 现在mysql自建集群方案有多种&#xff0c;keepalived、MHA、PXC、MYSQL主备等&#xff0c;但是目前根据自身情况和条件&#xff0c;选择使用pxc的放来进行搭建&#xff0c;最大的好处就是&#xff0c;多主多备&#xff0c;即主从一体&#xff0c;没有同步延时问题&#xf…