线程池 | java中的多线程

在 《Java异步编程 | CompletableFuture--实现复杂的异步控制流
》中,我们提到了 通过 自定义线程池 , 用于管理 异步任务的执行,避免频繁创建和销毁线程,提高性能。

本文将整理并介绍一些 Java 中常见的 多线程创建方式,用于 更好地理解和选择 合适的线程管理策略

本文整理了下述5种 创建多线程 的方式

  1. 实现 Runnable 接口
  2. 继承 Thread 类
  3. 使用 Callable 和 FutureTask
  4. 使用线程池(ExecutorService)
  5. CompletableFuture

一、实现 Runnable 接口

  • 方式:通过 实现 Runnable 接口的 run() 方法 ,定义线程要执行的任务,然后将 Runnable 对象 传入 Thread 构造函数,最后调用 start() 方法启动线程。
  • 优点:可以避免继承 Thread 类的限制,Runnable 可以被 多个线程共享
  • 代码示例
class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("Thread is running");
    }
}

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start();
    }
}

二、继承 Thread

  • 方式:直接 继承 Thread 类,并重写 run() 方法,创建 子类对象 并调用 start() 方法启动线程。
  • 优点:简单直观,适用于线程功能比较单一的情况。
  • 缺点:Java 不支持多重继承,因此如果已经继承了其他类,就不能再继承 Thread 类。
  • 代码示例
class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("Thread is running");
    }
}

public class Main {
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();
    }
}

三、使用 CallableFutureTask

  • 方式Callable 接口与 Runnable 类似,但它可以 返回结果抛出异常。通过 FutureTask 来包装 Callable 对象,再通过 Thread 启动。
  • 优点:可以获取任务的 执行结果,并处理异常。
  • 代码示例
class MyCallable implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        return 100;
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        FutureTask<Integer> task = new FutureTask<>(new MyCallable());
        Thread thread = new Thread(task);
        thread.start();
        Integer result = task.get(); // 获取任务执行结果
        System.out.println("Result: " + result);
    }
}

四、使用线程池(ExecutorService

  • 方式:线程池通过 ExecutorService 提供一个更高层的 API,管理线程的 创建、调度和销毁。可以使用线程池来提交 RunnableCallable 任务,避免手动管理线程,特别适合 处理大量并发任务
  • 优点:线程池能够重用线程,避免线程的频繁创建和销毁,提高了效率;还可以 控制并发线程的数量
  • 代码示例
class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("Thread is running in a thread pool");
    }
}

public class Main {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(10); // 创建一个大小为10的线程池
        executor.submit(new MyRunnable()); // 提交任务
        executor.shutdown(); // 关闭线程池
    }
}

(一) 核心方法

  • submit(Runnable task):提交一个没有返回值的任务。
  • submit(Callable<T> task):提交一个有返回值的任务,返回一个 Future<T> 对象,可以通过 get() 方法获取任务的执行结果。
  • invokeAll(Collection<? extends Callable<T>> tasks):提交一组任务并等待所有任务完成,返回每个任务的结果。
  • invokeAny(Collection<? extends Callable<T>> tasks):提交一组任务,返回最先完成的任务的结果。
  • shutdown():启动优雅关闭,停止接收新的任务,并等待现有任务完成。
  • shutdownNow():立即关闭线程池,尝试中断所有正在执行的任务并返回待执行的任务列表。

(二) ExecutorService 的实现类

Java 提供了几种常用的线程池实现类:

1. newFixedThreadPool(int nThreads)
  • 创建一个固定大小的线程池,线程池中始终有固定数量的线程。适合于处理需要固定线程数的任务。
  • 如果线程池中有线程空闲,新的任务将由空闲线程执行;如果线程池已满,新任务将被放入任务队列等待。

示例

ExecutorService executor = Executors.newFixedThreadPool(3);
2. newCachedThreadPool()
  • 创建一个可以根据需要创建新线程的线程池,如果线程池中的线程空闲超过60秒就会被回收。适合于执行大量短时间的异步任务。
  • 线程池的大小根据系统需求动态调整。

示例

ExecutorService executor = Executors.newCachedThreadPool();
3. newSingleThreadExecutor()
  • 创建一个只有一个线程的线程池,所有提交的任务将顺序执行。适合于需要按顺序执行任务的场景。

示例

ExecutorService executor = Executors.newSingleThreadExecutor();
4. newScheduledThreadPool(int corePoolSize)
  • 创建一个固定大小的线程池,适用于定时任务和周期性任务的执行。

示例

ScheduledExecutorService executor = Executors.newScheduledThreadPool(3);
executor.schedule(() -> {
    System.out.println("Scheduled task executed");
}, 1, TimeUnit.SECONDS);

(三) ExecutorService 的作用

  1. 管理线程池ExecutorService 负责创建和管理一个或多个线程池,它从池中获取线程来执行任务。与直接创建线程(如通过 new Thread())相比,使用线程池更加高效和灵活,特别是在处理大量短小任务时,线程池能有效避免线程频繁创建和销毁的开销。
  2. 任务提交: 它通过 submit() 方法将任务提交给线程池执行,返回一个 Future 对象,Future 允许我们获取任务的执行结果或取消任务。
  3. 任务调度ExecutorService 提供了强大的任务调度功能,可以安排任务在未来某个时刻执行,或者定期执行任务。例如,使用 schedule() 方法,任务可以按照固定的延迟执行或以固定的周期重复执行。
  4. 线程复用: 线程池内部维护了一组线程,线程池中的线程可以被复用,执行完一个任务后,线程会返回池中准备执行下一个任务。这样避免了每次执行任务都需要创建和销毁线程的性能消耗。
  5. 优雅关闭ExecutorService 提供了 shutdown() 方法来优雅地关闭线程池,这样线程池中的线程会完成正在执行的任务并终止,新的任务将不会被接受。它还提供了 shutdownNow() 方法,用于立即关闭线程池并尝试停止所有正在执行的任务。

五、CompletableFuture(本质也是线程池)

有关CompletableFuture,详见 《Java异步编程 | CompletableFuture–实现复杂的异步控制流》

  • 方式CompletableFuture 是 Java 8 引入的 API,用于处理异步编程。它可以非常方便地处理异步任务之间的依赖关系,并支持链式调用。它默认使用 ForkJoinPool 来执行任务,提供了比 Future 更强大的功能。
  • 优点:支持异步编程,并能链式调用,简化了异步任务的处理。
  • 代码示例
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
    System.out.println("Asynchronous task");
});

future.thenRun(() -> {
    System.out.println("Another task after first one");
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/957516.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SQL sever数据导入导出实验

1.创建数据库TCP-H &#xff08;1&#xff09;右键“数据库”&#xff0c;点击“新建数据库”即可 &#xff08;2&#xff09;用sql语言创建&#xff0c;此处以创建数据库DB_test为例&#xff0c;代码如下&#xff1a; use master;go--检查在当前服务器系统中的所有数据里面…

Codeforces Round 903 (Div. 3) E. Block Sequence

题解&#xff1a; 想到从后向前DP f[i] 表示从 i ~ n 转化为“美观”所需要的最少的步骤 第一种转移方式&#xff1a;直接删除掉第i个元素&#xff0c;那么就是上一步 f[i 1] 加上 1;第二种转移方式&#xff1a;从第 i a[i] 1 个元素直接转移&#xff0c;不需要增加步数&a…

linux-FTP服务配置与应用

也许你对FTP不陌生&#xff0c;但是你是否了解FTP到底是个什么玩意&#xff1f; FTP 是File Transfer Protocol&#xff08;文件传输协议&#xff09;的英文简称&#xff0c;而中文简称为 “文传协议” 用于Internet上的控制文件的双向传输。同时&#xff0c;它也是一个应用程序…

Alluxio 联手 Solidigm 推出针对 AI 工作负载的高级缓存解决方案

作者&#xff1a;Wayne Gao, Yi Wang, Jie Chen, Sarika Mehta Alluxio 作为全球领先的 AI 缓存解决方案供应商&#xff0c; 提供针对 GPU 驱动 AI 负载的高速缓存。其可扩展架构支持数万个节点&#xff0c;能显著降低存储带宽的消耗。Alluxio 在解决 AI 存储挑战方面的前沿技…

深度学习篇---AnacondaLabelImg

文章目录 前言第一部分&#xff1a;Anaconda是什么&#xff1f;1.简介2.特点&#xff08;1&#xff09;包管理器Conda&#xff08;2&#xff09;环境管理&#xff08;3&#xff09;预装包&#xff08;4&#xff09;跨平台&#xff08;5&#xff09;社区支持 3.安装WindowsLinux…

基于Redis实现短信验证码登录

目录 1 基于Session实现短信验证码登录 2 配置登录拦截器 3 配置完拦截器还需将自定义拦截器添加到SpringMVC的拦截器列表中 才能生效 4 Session集群共享问题 5 基于Redis实现短信验证码登录 6 Hash 结构与 String 结构类型的比较 7 Redis替代Session需要考虑的问题 8 …

Open3D计算点云粗糙度(方法一)【2025最新版】

目录 一、Roughness二、代码实现三、结果展示博客长期更新,本文最近更新时间为:2025年1月18日。 一、Roughness 通过菜单栏的Tools > Other > Roughness找到该功能。 这个工具可以估计点云的“粗糙度”。 选择一个或几个点云,然后启动这个工具。 CloudCompare只会询问…

(二叉树)

我们今天就开始引进一个新的数据结构了&#xff1a;我们所熟知的&#xff1a;二叉树&#xff1b; 但是我们在引进二叉树之前我们先了解一下树&#xff1b; 树 树的概念和结构&#xff1a; 树是⼀种⾮线性的数据结构&#xff0c;它是由 n &#xff08; n>0 &#xff09; …

洛谷P8837

[传智杯 #3 决赛] 商店 - 洛谷 代码区&#xff1a; #include<stdio.h> #include<stdlib.h> int cmp(const void*a,const void *b){return *(int*)b-*(int*)a; } int main(){int n,m;scanf("%d%d",&n,&m);int w[n];int c[m];for(int i0;i<n;…

C语言练习(17)

两个乒乓球队进行比赛&#xff0c;各出3人。甲队为A、B、C 3人&#xff0c;乙队为X、Y、Z 3人&#xff0c;并抽签决定比赛名单。有人向队员打听比赛的名单&#xff0c;A说他不和X比&#xff0c;C说他不和X、Z比&#xff0c;请编程序找出3对选手的对阵名单。 #include <stdi…

excel实用工具

持续更新… 文章目录 1. 快捷键1.1 求和 2. 命令2.1 查找 vloopup 1. 快捷键 1.1 求和 windows: alt mac : command shift T 2. 命令 2.1 查找 vloopup vlookup 四个入参数 要查找的内容 &#xff08;A2 6xx1&#xff09;查找的备选集 &#xff08;C2:C19&#xff09;…

【高阶数据结构】布隆过滤器(BloomFilter)

1. 概念 1.1 背景引入 背景&#xff1a;在计算机软件中&#xff0c;一个常见的需求就是 在一个集合中查找一个元素是否存在 &#xff0c;比如&#xff1a;1. Word 等打字软件需要判断用户键入的单词是否在字典中存在 2. 浏览器等网络爬虫程序需要保存一个列表来记录已经遍历过…

Linux内存管理(Linux内存架构,malloc,slab的实现)

文章目录 前言一、Linux进程空间内存分配二、malloc的实现机理三、物理内存与虚拟内存1.物理内存2.虚拟内存 四、磁盘和物理内存区别五、页页的基本概念&#xff1a;分页管理的核心概念&#xff1a;Linux 中分页的实现&#xff1a;总结&#xff1a; 六、伙伴算法伙伴算法的核心…

2025/1/21 学习Vue的第四天

睡觉。 --------------------------------------------------------------------------------------------------------------------------------- 11.Object.defineProperty 1.在我们之前学习JS的时候&#xff0c;普通得定义一个对象与属性。 <!DOCTYPE html> <h…

机器学习10-解读CNN代码Pytorch版

机器学习10-解读CNN代码Pytorch版 我个人是Java程序员&#xff0c;关于Python代码的使用过程中的相关代码事项&#xff0c;在此进行记录 文章目录 机器学习10-解读CNN代码Pytorch版1-核心逻辑脉络2-参考网址3-解读CNN代码Pytorch版本1-MNIST数据集读取2-CNN网络的定义1-无注释版…

python学opencv|读取图像(四十)掩模:三通道图像的局部覆盖

【1】引言 前序学习了使用numpy创建单通道的灰色图像&#xff0c;并对灰色图像的局部进行了颜色更改&#xff0c;相关链接为&#xff1a; python学opencv|读取图像&#xff08;九&#xff09;用numpy创建黑白相间灰度图_numpy生成全黑图片-CSDN博客 之后又学习了使用numpy创…

【MySQL篇】使用mysqldump导入报错Unknown collation: ‘utf8mb4_0900_ai_ci‘的问题解决

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;从事IT领域✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长阿里云AnalyticDB for MySQL(分布式数据仓库)、Oracle、MySQL、Linux、prometheus监控&#xff1b;并对SQLserver、NoSQL(…

WPF2-在xaml为对象的属性赋值

1. AttributeValue方式 1.1. 简单属性赋值1.2. 对象属性赋值 2. 属性标签的方式给属性赋值3. 标签扩展 (Markup Extensions) 3.1. StaticResource3.2. Binding 3.2.1. 普通 Binding3.2.2. ElementName Binding3.2.3. RelativeSource Binding3.2.4. StaticResource Binding (带参…

软考 系统架构设计师系列知识点之面向服务架构设计理论与实践(5)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之面向服务架构设计理论与实践&#xff08;4&#xff09; 所属章节&#xff1a; 第15章. 面向服务架构设计理论与实践 第2节 SOA的发展历史 15.2 SOA的发展历史 15.2.3 SOA的微服务化发展 随着互联网技术的快速发展&a…

ICLR顶会论文学习|DRL-based改进启发式求解方法JSSP

论文名&#xff1a;Deep Reinforcement Learning Guided Improvement Heuristic for Job Shop Scheduling Authors: Cong Zhang, Zhiguang Cao, Wen Song, Yaoxin Wu, Jie Zh… 论文发表致&#xff1a;ICLR 2024 论文链接&#xff1a;https://doi.org/10.48550/arXiv.2211.1…