线程池的使用(7种创建方法)

article/2025/9/14 17:10:08

目录

 1. 固定数量的线程池

a.  线程池返回结果

b. ⾃定义线程池名称或优先级

2. 带缓存的线程池

3. 执⾏定时任务

a. 延迟执⾏(⼀次)

b. 固定频率执⾏

c. scheduleAtFixedRate VS scheduleWithFixedDelay

4. 定时任务单线程

5. 单线程线程池

6. 根据当前CPU⽣成线程池

7. ThreadPoolExecutor


线程池的创建⽅法总共有 7 种,但总体来说可分为 2 类:
        1. 通过 ThreadPoolExecutor 创建的线程池;
        2. 通过 Executors 创建的线程池。
线程池的创建⽅式总共包含以下 7 种(其中 6 种是通过 Executors 创建的, 1 种是通过
ThreadPoolExecutor 创建的):
        1. Executors.newFixedThreadPool:创建⼀个固定⼤⼩的线程池,可控制并发的线程数,超出的线程会在队列中等待;
        2. Executors.newCachedThreadPool:创建⼀个可缓存的线程池,若线程数超过处理所需,缓存⼀段时间后会回收,若线程数不够,则新建线程;
        3. Executors.newSingleThreadExecutor:创建单个线程数的线程池,它可以保证先进先出的执⾏顺序;
        4. Executors.newScheduledThreadPool:创建⼀个可以执⾏延迟任务的线程池;
        5. Executors.newSingleThreadScheduledExecutor:创建⼀个单线程的可以执⾏延迟任务的线程池;

        6. Executors.newWorkStealingPool:创建⼀个抢占式执⾏的线程池(任务执⾏顺序不确定)【JDK1.8 添加】。
        7. ThreadPoolExecutor:最原始的创建线程池的⽅式,它包含了 7 个参数可供设置,后⾯会详细讲。

 1. 固定数量的线程池

public class ThreadPoolDemo3 {public static void main(String[] args) {ExecutorService threadPool = Executors.newFixedThreadPool(2);//添加任务方式 1threadPool.submit(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName());}});//添加任务方式2threadPool.execute(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName());}});}
}
输出:
pool-1-thread-1
pool-1-thread-2

a.  线程池返回结果

public class ThreadPoolDemo4 {public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService threadPool =  Executors.newFixedThreadPool(2);//执行任务Future<Integer> result = threadPool.submit(new Callable<Integer>() {@Overridepublic Integer call() throws Exception {int num = new Random().nextInt(10);System.out.println("随机数" + num);return num;}});//打印线程池返回方式System.out.println("返回结果:" + result.get());}
}
输出
随机数8
返回结果:8

使用submit可以执行有返回值的任务或者是无返回值的任务;而execute只能执行不带返回值的任务。 

b. ⾃定义线程池名称或优先级

public class ThreadPoolDemo5 {public static void main(String[] args) throws ExecutionException, InterruptedException {// 创建线程工厂ThreadFactory threadFactory = new ThreadFactory() {@Overridepublic Thread newThread(Runnable r) {//!!!!!!!一定要注意:要把任务Runnable设置给新创建的线程Thread thread = new Thread(r);//设置线程的命名规则thread.setName("我的线程" + r.hashCode());//设置线程的优先级thread.setPriority(Thread.MAX_PRIORITY);return thread;}};ExecutorService threadPool = Executors.newFixedThreadPool(2,threadFactory);//执行任务1Future<Integer> result = threadPool.submit(new Callable<Integer>() {@Overridepublic Integer call() throws Exception {int num = new Random().nextInt(10);System.out.println(Thread.currentThread().getPriority() + ", 随机数:" + num);return num;}});//打印线程池返回结果System.out.println("返回结果:" + result.get());}
}

 提供的功能:

        1. 设置(线程池中)线程的命名规则。

        2. 设置线程的优先级。

        3. 设置线程分组。

        4. 设置线程类型(用户线程、守护线程)。

2. 带缓存的线程池

public class ThreadPoolDemo6 {public static void main(String[] args) {//创建线程池ExecutorService service = Executors.newCachedThreadPool();for (int i = 0; i < 10; i++) {int finalI = i;service.submit(() -> {System.out.println("i : " + finalI + "|线程名称:" + Thread.currentThread().getName());});}}
}
输出
i : 1|线程名称:pool-1-thread-2
i : 4|线程名称:pool-1-thread-5
i : 3|线程名称:pool-1-thread-4
i : 5|线程名称:pool-1-thread-6
i : 0|线程名称:pool-1-thread-1
i : 2|线程名称:pool-1-thread-3
i : 6|线程名称:pool-1-thread-7
i : 7|线程名称:pool-1-thread-8
i : 8|线程名称:pool-1-thread-9
i : 9|线程名称:pool-1-thread-1

 优点:线程池会根据任务数量创建线程池,并且在一定时间内可以重复使用这些线程,产生相应的线程池。

缺点:适用于短时间有大量任务的场景,它的缺点是可能会占用很多的资源。

3. 执⾏定时任务

a. 延迟执⾏(⼀次)

public class ThreadPoolDemo7 {public static void main(String[] args) {//创建线程池ScheduledExecutorService service = Executors.newScheduledThreadPool(5);System.out.println("添加任务的时间:" + LocalDateTime.now());//执行定时任务(延迟3s执行)只执行一次service.schedule(new Runnable() {@Overridepublic void run() {System.out.println("执行子任务:" + LocalDateTime.now());}},3, TimeUnit.SECONDS);}
}
输出
添加任务的时间:2022-04-13T14:19:39.983
执行子任务:2022-04-13T14:19:42.987

  

b. 固定频率执⾏

public class ThreadPoolDemo8 {public static void main(String[] args) {//创建线程池ScheduledExecutorService service = Executors.newScheduledThreadPool(5);System.out.println("添加任务时间:" + LocalDateTime.now());//2s之后开始执行定时任务,定时任务每隔4s执行一次service.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {System.out.println("执行任务:" + LocalDateTime.now());}},2,4, TimeUnit.SECONDS);}
}
输出
添加任务时间:2022-04-13T14:24:38.810
执行任务:2022-04-13T14:24:40.814
执行任务:2022-04-13T14:24:44.814
执行任务:2022-04-13T14:24:48.813
执行任务:2022-04-13T14:24:52.815
执行任务:2022-04-13T14:24:56.813
执行任务:2022-04-13T14:25:00.813
执行任务:2022-04-13T14:25:04.814
执行任务:2022-04-13T14:25:08.813
... ...
... ...
执行任务:2022-04-13T14:26:44.814
执行任务:2022-04-13T14:26:48.813

 注意事项:

public class ThreadPoolDemo9 {public static void main(String[] args) {//创建线程池ScheduledExecutorService service = Executors.newScheduledThreadPool(5);System.out.println("添加任务时间:" + LocalDateTime.now());service.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {System.out.println("执行任务: " + LocalDateTime.now());try {Thread.sleep(5 * 1000);} catch (InterruptedException e) {e.printStackTrace();}}},2,4, TimeUnit.SECONDS);}
}
输出
添加任务时间:2022-04-13T14:33:34.551
执行任务: 2022-04-13T14:33:36.556
执行任务: 2022-04-13T14:33:41.557
执行任务: 2022-04-13T14:33:46.559
执行任务: 2022-04-13T14:33:51.561
执行任务: 2022-04-13T14:33:56.562
执行任务: 2022-04-13T14:34:01.564
执行任务: 2022-04-13T14:34:06.566
执行任务: 2022-04-13T14:34:11.566
执行任务: 2022-04-13T14:34:16.567
执行任务: 2022-04-13T14:34:21.570
执行任务: 2022-04-13T14:34:26.570
... ....

c. scheduleAtFixedRate VS scheduleWithFixedDelay

scheduleAtFixedRate 是以上⼀次任务的开始时间,作为下次定时任务的参考时间的(参考时间+延迟任务=任务执⾏)。
scheduleWithFixedDelay 是以上⼀次任务的结束时间,作为下次定时任务的参考时间的。
public class ThreadPoolDemo10 {public static void main(String[] args) {//创建线程池ScheduledExecutorService service = Executors.newScheduledThreadPool(5);System.out.println("添加任务时间:" + LocalDateTime.now());//2s之后开始执行定时任务,定时任务每隔4s执行一次service.scheduleWithFixedDelay(new Runnable() {@Overridepublic void run() {System.out.println("执行任务:" + LocalDateTime.now());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}, 2, 4, TimeUnit.SECONDS);}
}
输出
添加任务时间:2022-04-13T14:46:02.871
执行任务:2022-04-13T14:46:04.876
执行任务:2022-04-13T14:46:09.878
执行任务:2022-04-13T14:46:14.880
执行任务:2022-04-13T14:46:19.883
执行任务:2022-04-13T14:46:24.885
执行任务:2022-04-13T14:46:29.888
执行任务:2022-04-13T14:46:34.888
执行任务:2022-04-13T14:46:39.891
执行任务:2022-04-13T14:46:44.893
执行任务:2022-04-13T14:46:49.895
执行任务:2022-04-13T14:46:54.897
执行任务:2022-04-13T14:46:59.900
执行任务:2022-04-13T14:47:04.901
... ...

4. 定时任务单线程

public class ThreadPoolDemo11 {public static void main(String[] args) {ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();System.out.println("添加任务的时间:" + LocalDateTime.now());service.schedule(new Runnable() {@Overridepublic void run() {System.out.println("执行时间:" + LocalDateTime.now());}},2, TimeUnit.SECONDS );}
}
输出
添加任务的时间:2022-04-13T15:06:38.100
执行时间:2022-04-13T15:06:40.106

5. 单线程线程池

public class ThreadPoolDemo12 {public static void main(String[] args) {ExecutorService service = Executors.newSingleThreadScheduledExecutor();for (int i = 0; i < 10; i++) {service.submit(new Runnable() {@Overridepublic void run() {System.out.println("线程名:" + Thread.currentThread().getName());}});}}
}
输出
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1

(MS) 为什么不直接用线程?

单线程的线程池又什么意义?

        1. 复用线程。

        2. 单线程的线程池提供了任务队列和拒绝策略(当任务队列满了之后(Integer.MAX_VALUE),新来的任务就会拒绝策略)

6. 根据当前CPU⽣成线程池

public class ThreadPoolDemo13 {public static void main(String[] args) {ExecutorService service = Executors.newWorkStealingPool();for (int i = 0; i < 10; i++) {service.submit(() -> {System.out.println("线程名" + Thread.currentThread().getName());});while(!service.isTerminated()) {}}}
}
输出
线程名ForkJoinPool-1-worker-1

7. ThreadPoolExecutor

线程池的使用(7种创建方法)_Youcan.的博客-CSDN博客https://blog.csdn.net/m0_48273471/article/details/124171220


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

相关文章

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

目录 前言常用的四种线程池newCachedThreadPool——可缓存线程池newFixedThreadPool————指定线程数量newSingleThreadExecutor————单线程的ExecutornewScheduleThreadPool——定时线程池 线程池七大参数corePoolSize——核心线程最大数maximumPoolSize——线程池最大线…

创建线程池的七种方式

在 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 这里我的服务器版本为…