Java 高级应用-多线程-(三)实现 Callable 接口与使用线程池创建线程

news2024/11/29 12:55:17

实现 Callable 接口
• 与使用 Runnable 相比, Callable 功能更强大些
– 相比 run()方法,可以有返回值
– 方法可以抛出异常
支持泛型的返回值(需要借助 FutureTask 类,获取返回结果)

• Future 接口(了解)
– 可以对具体 Runnable、Callable 任务的执行结果进行取消、查询是否完
成、获取结果等。
– FutureTask 是 Futrue 接口的唯一的实现类
– FutureTask 同时实现了 Runnable, Future 接口。它既可以作为 Runnable 被线程执行,又可以作为 Future 得到 Callable 的返回值
• 缺点:在获取分线程执行结果的时候,当前线程(或是主线程)受阻塞,效率较低。
代码举例:

/*
* 创建多线程的方式三:实现 Callable (jdk5.0 新增的)
*/
//1.创建一个实现 Callable 的实现类
class NumThread implements Callable {
 //2.实现 call 方法,将此线程需要执行的操作声明在 call()中
 @Override
 public Object call() throws Exception {
 int sum = 0;
 for (int i = 1; i <= 100; i++) {
 if (i % 2 == 0) {
 System.out.println(i);
 sum += i;
 }
 }
 return sum;
 }
}
public class CallableTest {
 public static void main(String[] args) {
 //3.创建 Callable 接口实现类的对象
 NumThread numThread = new NumThread();
 //4.将此 Callable 接口实现类的对象作为传递到 FutureTask 构造器中,创建 FutureTask 的对象
 FutureTask futureTask = new FutureTask(numThread);
 //5.将 FutureTask 的对象作为参数传递到 Thread 类的构造器中,创建 Thread 对象,并调用 start()
 new Thread(futureTask).start();
// 接收返回值
 try {
 //6.获取 Callable 中 call 方法的返回值
 //get()返回值即为 FutureTask 构造器参数 Callable 实现类重写的 call()的返回值。
 Object sum = futureTask.get();
 System.out.println("总和为:" + sum);
 } catch (InterruptedException e) {
 e.printStackTrace();
 } catch (ExecutionException e) {
 e.printStackTrace();
 }
 }
}

使用线程池
现有问题:
如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。

那么有没有一种办法使得线程可以复用,即执行完一个任务,并不被销毁,而是可以继续执行其他的任务?

思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建销毁、实现重复利用。类似生活中的公共交通工具。

在这里插入图片描述

好处:
• 提高响应速度(减少了创建新线程的时间)
• 降低资源消耗(重复利用线程池中线程,不需要每次都创建)
• 便于线程管理
– corePoolSize:核心池的大小
– maximumPoolSize:最大线程数
– keepAliveTime:线程没有任务时最多保持多长时间后会终止
– …
线程池相关 API
• JDK5.0 之前,我们必须手动自定义线程池。从 JDK5.0 开始,Java 内置线程池相关的
API。在 java.util.concurrent 包下提供了线程池相关 API:ExecutorService 和
Executors。
• ExecutorService:真正的线程池接口。常见子类 ThreadPoolExecutor
– void execute(Runnable command) :执行任务/命令,没有返回值,
一般用来执行 Runnable
– Future submit(Callable task):执行任务,有返回
值,一般又来执行 Callable
– void shutdown() :关闭连接池
• Executors:一个线程池的工厂类,通过此类的静态工厂方法可以创建多种类型的线
程池对象。
– Executors.newCachedThreadPool():创建一个可根据需要创建新线
程的线程池
– Executors.newFixedThreadPool(int nThreads); 创建一个可重用
固定线程数的线程池
– Executors.newSingleThreadExecutor() :创建一个只有一个线程的
线程池
– Executors.newScheduledThreadPool(int corePoolSize):创建
一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
代码举例:

class NumberThread implements Runnable{
 @Override
 public void run() {
 for(int i = 0;i <= 100;i++){
 if(i % 2 == 0){
 System.out.println(Thread.currentThread().getName() +
": " + i);
 }
 }
 }
}
class NumberThread1 implements Runnable{
 @Override
 public void run() {
 for(int i = 0;i <= 100;i++){
 if(i % 2 != 0){
 System.out.println(Thread.currentThread().getName() +
": " + i);
 }
 }
 }
}
class NumberThread2 implements Callable {
 @Override
 public Object call() throws Exception {
 int evenSum = 0;//记录偶数的和
 for(int i = 0;i <= 100;i++){
 if(i % 2 == 0){
 evenSum += i;
 }
 }
 return evenSum;
 }
}
public class ThreadPoolTest {
 public static void main(String[] args) {
 //1. 提供指定线程数量的线程池
 ExecutorService service = Executors.newFixedThreadPool(10);
 ThreadPoolExecutor service1 = (ThreadPoolExecutor) service;
// //设置线程池的属性
// System.out.println(service.getClass());//ThreadPoolExecutor
 service1.setMaximumPoolSize(50); //设置线程池中线程数的上限
 //2.执行指定的线程的操作。需要提供实现 Runnable 接口或 Callable 接口实现类的对象
 service.execute(new NumberThread());//适合适用于 Runnable
 service.execute(new NumberThread1());//适合适用于 Runnable
 try {
 Future future = service.submit(new NumberThread2());//适合使用于 Callable
 System.out.println("总和为:" + future.get());
 } catch (Exception e) {
 e.printStackTrace();
 }
 //3.关闭连接池
 service.shutdown();
 }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

游戏研发项目管理

基于阶段模式进行游戏新产品研发过程&#xff0c;以及基于这种研发过程Leangoo 领歌提供的项目模板。 二、游戏产品开发流程 通常开发一款新游戏大体上会按照如下流程来进行&#xff1a; 1&#xff09; 概念阶段 – Concept 主策根据产品创意&#xff0c;确定游戏策划草案&a…

C++中的内存空间管理详解【C++】

文章目录 C/C内存分布C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/freeC内存管理方式new/delete操作内置类型new和delete操作自定义类型 operator new与operator delete函数重载operator new与operator deletenew和delete的实现原理内置类型自定义类型 定位new表…

使用tomcat可能遇到的问题

问题一&#xff1a;窗口一闪而过 如果双击startup.bat&#xff0c;启动tomcat&#xff0c;命令窗口一闪而过&#xff1b;或者用命令窗口执行startup.bat命令&#xff0c;未能启动tomcat&#xff0c;而是提示下面的文字&#xff1b; 说明可能是java的环境变量配置错误&#xf…

让ChatGPT谈谈科技发展

ChatGPT谈科技发展 讲讲科技发展的那些事儿谈谈ChatGPT对科技发展的影响谈谈你对ChatGPT的看法ChatGPT对科技发展的负面影响ChatGPT的存在是利是弊&#xff1f;关于全国科技者工作日 讲讲科技发展的那些事儿 谈谈ChatGPT对科技发展的影响 谈谈你对ChatGPT的看法 ChatGPT对科技发…

pdf怎么合并成一个文件?高效工具分享

PDF是一种非常常用的文档格式&#xff0c;许多人经常需要合并多个PDF文件为一个文件。这是因为有时候我们需要将多个PDF文件打包成一个文件&#xff0c;以便于共享或归档。在本文中&#xff0c;我们将介绍如何使用电脑或手机合并PDF文件。 以下是常见的合并PDF的软件&#xff1…

以太坊Layer 2即将爆发!加密巨头入场布局,或将迎来“百链大战”!

眼下&#xff0c;以太坊Layer 2发展势头强劲。在数十条Rollup Layer 2异彩纷呈之际&#xff0c;Coinbase、ConsenSys等加密巨头也开始下场参与竞争&#xff0c;部署原生Layer 2网络。 截至2022年底&#xff0c;Layer 2解决方案的日均交易数在持续增加&#xff0c;甚至超过了以太…

牛客网语法篇刷题(C语言) — 基本类型

&#x1f929;本文作者&#xff1a;大家好&#xff0c;我是paperjie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 &#x1f970;内容专栏&#xff1a;这里是《C语言—语法篇》专栏&#xff0c;笔者用重金(时间和精力)打造&#xff0c;基础知识一网打尽&#xff0c;…

如何制作插件使用案例?

UE5 插件开发指南 前言0 示例角色蓝图1测试关卡2 扩展物品数据3 小结前言 作为一款插件,我们一定想要开发者拿到之后立即知道如何使用,所以我们需要制作插件使用案例,最好搭配相应的文档教会插件的使用者如何使用插件,如何对插件的功能进行扩展。为了达到这样的目标,我们…

TOPSIS(优劣解距离法)【附Python实现代码及可视化代码】

目录 一、指标正向化 1.极小型指标->极大型指标 2.中间型指标->极大型指标 3.区间型指标->极大型指标 二、标准化处理 三、计算得分并归一化(不带权重) 四、计算得分并归一化(带权重) 熵权法 1&#xff09;判断输入的矩阵是否存在负数 2&#xff09;计算第j…

通过 Wacom 的 Project Mercury 提高远程办公效率

过去几年中&#xff0c;我们的工作方式发生了翻天覆地的变化。疫情加快了对远程办公和协作的采纳&#xff0c;导致人们更加依赖技术来联系团队和提高工作效率。 但是&#xff0c;那些依靠专门硬件和软件来完成工作的创作者呢&#xff1f;艺术家、设计师和开发人员需要使用专门…

34 KVM管理设备-管理虚拟磁盘

文章目录 34 KVM管理设备-管理虚拟磁盘34.1 概述34.2 操作步骤 34 KVM管理设备-管理虚拟磁盘 34.1 概述 虚拟磁盘类型主要包含virtio-blk、virtio-scsi、vhost-scsi等。virtio-blk模拟的是一种block设备&#xff0c;virtio-scsi和vhost-scsi模拟的是一种scsi设备。 virtio-b…

window部署redis集群

1.下载Redis-x64-3.2.100.zip 下载网址&#xff1a;https://github.com/microsoftarchive/redis 百度网盘下载&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;j2js redis版本一定要大于3.0&#xff0c;原因&#xff1a;windows暂不支持redis-cli创建集群&#xff0c;…

TPP0100泰克无源电压探头

tektronix泰克TPP0100 和 TPP0101无源电压探头是输入电阻为 10 M? 的 100 MHz、10X 无源电压探头。这些探头是和 1 MΩ/13 pF (TPP0100) 和 1 MΩ/20 pF (TPP0101) 输入的 BNC示波器搭配 使用。 tektronix泰克TPP0100无源电压探头特点 带宽 直流至 100 M…

Day5 统计回文、连续最大和

✨个人主页&#xff1a; 北 海 &#x1f389;所属专栏&#xff1a; C/C相关题解 &#x1f383;操作环境&#xff1a; Visual Studio 2019 版本 16.11.17 文章目录 选择题1.C指针/链表/结构 编程题1.统计回文2.连续最大和 选择题 1.C指针/链表/结构 题目&#xff1a;下面两个结…

MySQL 性能调优及生产实战篇终版

前言为什么会查询慢&#xff1f;优化数据访问查询数据低效原因是否请求了不需要的数据 优化执行过程查询缓存查询优化处理语法解析器查询优化器优化器的优化策略优化器的优化类型关联查询排序优化 大数据量查询优化优化 COUNT 查询优化关联查询优化子查询优化 LIMIT 分页优化 u…

Laetus控制器维修20C-A323包装机控制模块

LAETUS 旗下系列有&#xff1a; ARGUS 、 POLYPHEM 、 INSPECT 等均可维修。Laetus GmbH控制器维修28C-A353&#xff0c;设备控制模块维修。 Laetus GmbH部分产品维修型号&#xff1a; Laetus 2D COSI wt &#xff1b; Laetus 2D COSI wt Laetus TDK Lambda HK15 Laetus 2D-…

别再瞎考证了!关于网络安全行业的证书,看完这篇,明明白白考证

有相关证书会让你的职业生涯锦上添花&#xff0c;实战技术能力必不可少。 温馨提示&#xff1a; 1、不满足条件的高校学生群体&#xff0c;可以直接报名考取NISP二级证书&#xff0c;满足CISP认证要求后&#xff0c;免考试按规定更换CISP证书&#xff0c;为毕业后从事网络安全…

一切从“简”,解放IT运维人员

运维人的神技 运维既是个技术活儿也是个苦差事&#xff0c;而运维人员被期望有着无限的技能&#xff1a;主机、存储、网络、操作系统样样精通&#xff0c;而且还要会写SQL、shell、开发语言java、.net、python等等&#xff0c;对业务更是门清&#xff0c;对各个用户的脾气喜好也…

vector常见接口的使用(基于c++标准库中的STL)

前言 vector是STL中的重要容器&#xff0c;在平时使用中较常见。学会使用它以及了解它的核心原理对于我们学习它是很有帮助的。vector是可以动态增长的数组。vector可以像数组一样进行随机访问&#xff0c;这是vector最大的优势之一&#xff0c;因为支持随机访问就间接的支持了…

TRUNCATE TABLE t 和DELETE FROM t的区别

背景 最近再工作中,遇到一个问题,就是再代码执行过程中,出现异常时并不会去回滚代码.导致数据不一致,最初以为是Transactional这个注解没有生效 Spring中什么时候Transactional会失效 因为Spring事务是基于代理来实现的,所以某个加了Transactional的方法只有是被代理对象调用…