java中实现Callable方式创建线程

一、为啥要引入Callable

在前面讲了通过继承Thread和实现Runnable方式创建线程的区别,那为什么有了Runnable还要引入Callable?下面通过实现Runnable方式的弊端给出答案

实现Runnable方式的弊端:

package java.lang;
@FunctionalInterface
public interface Runnable {public abstract void run();
}package java.util.concurrent;
@FunctionalInterface
public interface Callable<V> {V call() throws Exception;
}

通过上面两个接口的定义可以看出

1、实现Runnable的方式没有返回值

2、实现Runnable的方式无法抛出异常

注:实现Callable方式是JDK1.5引入的

二、如何通过实现Callable方式创建线程

如何创建

这种方式创建线程需要配合FutureTask或者线程池来实现,下面给出通过配合FutureTask来创建线程的代码

public static void main(String[] args) {//1、定义一个Callable任务Callable<String> task = new Callable<String>() {@Overridepublic String call() throws Exception {System.out.println("任务正在执行"+Thread.currentThread().getName());return "OK";}};//2、创建FutureTask对象,传入刚创建的taskFutureTask<String> futureTask = new FutureTask<>(task);//3、创建线程并执行FutureTaskThread thread = new Thread(futureTask);thread.start();}

运行结果:
在这里插入图片描述
如何获取返回值

通过FutureTask的get方法可以获取返回值

public static void main(String[] args) {//1、定义一个Callable任务Callable<String> task = new Callable<String>() {@Overridepublic String call() throws Exception {System.out.println("任务正在执行"+Thread.currentThread().getName());return "OK";//返回一个值}};//2、创建FutureTask对象,传入刚创建的taskFutureTask<String> futureTask = new FutureTask<>(task);//3、创建线程并执行FutureTaskThread thread = new Thread(futureTask);thread.start();//4、获取返回值try {String result = futureTask.get();System.out.println("返回值:"+result);} catch (Exception e) {throw new RuntimeException(e);}}

执行结果:
在这里插入图片描述
因为call方法可能会抛出异常所以需要使用try…catch捕获

取消当前线程

FutureTask.java
public boolean cancel(boolean mayInterruptIfRunning) {if (!(state == NEW &&UNSAFE.compareAndSwapInt(this, stateOffset, NEW,mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))return false;try {    // in case call to interrupt throws exceptionif (mayInterruptIfRunning) {try {Thread t = runner;if (t != null)t.interrupt();} finally { // final stateUNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);}}} finally {finishCompletion();}return true;
}

FutureTask类中提供了一个cancel方法用于取消当前线程,下面是使用实例

public static void main(String[] args) {//1、定义一个Callable任务Callable<String> task = new Callable<String>() {@Overridepublic String call() throws Exception {try {for (int i = 0; i < 10; i++) {System.out.println("Task running... " + i);Thread.sleep(1000); // 模拟任务的执行}return "OK";} catch (InterruptedException e) {System.out.println("Task was interrupted");throw e;}}};//2、创建FutureTask对象,传入刚创建的taskFutureTask<String> futureTask = new FutureTask<>(task);//3、创建线程并执行FutureTaskThread thread = new Thread(futureTask);thread.start();try {// 主线程等待 3 秒钟,然后取消任务Thread.sleep(3000);System.out.println("Cancelling the task...");futureTask.cancel(true); // 取消任务,并设置为允许中断线程// 检查任务是否被取消if (futureTask.isCancelled()) {System.out.println("Task was cancelled");} else {// 尝试获取任务结果(这行代码可能永远不会执行,因为任务已经被取消)String result = futureTask.get();System.out.println("Task result: " + result);}} catch (Exception e) {e.printStackTrace();}}

执行结果:
在这里插入图片描述
注:实现Runnable创建线程的方式是没有cancel方法来取消当前任务的

三、配合线程池一起使用

public static void main(String[] args) {// 创建一个固定线程池ExecutorService executorService = Executors.newFixedThreadPool(3);// 定义一个 Callable 任务Callable<String> task = new Callable<String>() {@Overridepublic String call() throws Exception {if (Math.random() > 0.5) {throw new RuntimeException("Random failure occurred");}return "Task completed successfully";}};// 提交任务给线程池并获取 Future 对象Future<String> future = executorService.submit(task);try {// 获取任务的结果String result = future.get();System.out.println("Result: " + result);} catch (InterruptedException e) {// 线程被中断时的处理e.printStackTrace();} catch (ExecutionException e) {// call 方法抛出的异常会被封装在 ExecutionException 中Throwable cause = e.getCause();if (cause instanceof Exception) {// 处理 call 方法抛出的异常System.err.println("Exception caught: " + cause.getMessage());}}// 关闭线程池executorService.shutdown();}

执行结果:
在这里插入图片描述
当call方法中Math.random() > 0.5成立时执行结果为
在这里插入图片描述

四、总结

1、实现Callable的方式有返回值

2、实现Callable的方式可以抛出异常

3、实现Callable的方式可以通过FutureTask类中提供了一个cancel方法取消任务

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

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

相关文章

1095 解码PAT准考证(测试点3)

solution 测试点3超时&#xff1a;命令为3时&#xff0c;用unordered_map而非map&#xff0c;否则会超时 #include<iostream> #include<string> #include<algorithm> #include<unordered_map> using namespace std; const int maxn 1e4 10; struct…

2024山东大学软件学院创新项目实训(9)使用OpenCompass进行模型评估

下载好OpenCompassData-core-20231110.zip 之后&#xff0c;解压压缩包 unzip OpenCompassData-core-20231110.zip 运行代码&#xff1a; python run.py --datasets ceval_gen --hf-path /hy-tmp/7B21/merged --tokenizer-path /hy-tmp/7B21/merged --tokenizer-kwargs p…

步步精:连接器领域的卓越品牌

自1987年成立以来&#xff0c;步步精坐落于美丽的旅游城市——温州市乐清虹桥镇&#xff0c;被誉为“国家电子主体生产基地”、“国家精密模具制造基地”。公司拥有7大厂区、9大事业部&#xff0c;800名专职员工&#xff0c;致力于提供高品质的连接器解决方案。注册商标“BBJCO…

百度ai人脸识别项目C#

一、项目描述 本项目通过集成百度AI人脸识别API&#xff0c;实现了人脸检测和识别功能。用户可以上传图片&#xff0c;系统将自动识别人脸并返回识别结果。 二、开发环境 Visual Studio 2019或更高版本.NET Framework 4.7.2或更高版本AForge.NET库百度AI平台人脸识别API 三、…

从网络配置文件中提取PEAP凭据

我的一位同事最近遇到了这样一种情况&#xff1a;他可以物理访问使用802.1X连接到有线网络的Windows计算机&#xff0c;同时保存了用于身份验证的用户凭据&#xff0c;随后他想提取这些凭据&#xff0c;您可能认为这没什么特别的&#xff0c;但是事情却有点崎岖波折…… 如何开…

攻防世界-5-1

下载文件发现是一个没有尾缀的文件&#xff0c;扔winhex&#xff0c;emmmm还是没看出来 搜了一圈&#xff0c;发现用xortool 得到key之后&#xff0c;跑一下脚本 得到flag&#xff1a; wdflag{You Are Very Smart}

pytest测试框架pytest-sugar插件生成进度条

Pytest提供了丰富的插件来扩展其功能&#xff0c;介绍下插件pytest-sugar&#xff0c;可以帮助我们在控制台中显示彩色的测试结果和进度条&#xff0c;提供失败的堆栈回溯信息。 为了使用 pytest-sugar&#xff0c;需要满足以下条件&#xff1a; Python 3.8 或更高版本pytest…

并行计算之SIMD与SPMD

SIMD (Single Instruction Multiple Data) SIMD&#xff0c;也就是单指令多数据计算&#xff0c;一条指令可以处理多个数据。通过向量寄存器存储多个数据元素&#xff0c;并使用单条指令同时对这些数据元素进行处理&#xff0c;从而提高了计算效率。 代码示例&#xff1a; fl…

联想Y7000P 2023款拆机教程及升级内存教程

0.电脑参数介绍 联想Y7000P 2023电脑&#xff0c;笔者电脑CPU为i7-13700H&#xff0c;14核20线程&#xff1b;标配内存为三星的DDR5-5600MHz-8GB*2&#xff0c;由于电脑CPU限制&#xff0c;实际内存跑的频率为5200MHz; 2个内存插槽&#xff0c;2个固态硬盘插槽。每个内存插槽最…

FineReport报表案例

普通报表 保存的文件类型为 cpt&#xff0c;依靠着单元格的扩展与父子格的关系来实现模板效果&#xff0c;可进行参数查询&#xff0c;填报报表&#xff0c;图表设计等等&#xff0c;但是在分页预览模式下不能在报表主体中展示控件&#xff0c;而且单元格间相互影响&#xff0c…

1.2 DataX 数据同步工具详细介绍

DataX 是阿里巴巴开源的一款高效的数据同步工具&#xff0c;旨在实现多种异构数据源之间的高效数据同步。以下是对 DataX 的详细介绍&#xff1a; 架构 DataX 的架构主要包括以下几个核心组件&#xff1a; DataX Core&#xff1a;负责任务调度、插件加载、日志管理等核心功能…

鞋子分类数据集17399张69类别

数据集类型&#xff1a;图像分类用&#xff0c;不可用于目标检测无标注文件 数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;17399 分类类别数&#xff1a;69 类别名称:[“0”,“1”,“2”,“3”,“4”…

VisualBox 虚拟机 Ubunut 18.04 在大显示器上黑屏的问题

在小屏幕上显示没有问题&#xff0c;但是移动到大显示器上就黑屏了&#xff0c;并且不能铺满&#xff0c;如下所示 如果我希望它铺满整个屏幕&#xff0c;如何解决呢&#xff1f; 下面是解决方法&#xff1a; 虚拟机底部这个按钮&#xff0c;右键 产生菜单&#xff0c;按这个选…

09--keepalived高可用集群

前言&#xff1a;高可用集群配置是大型网站的一个基础&#xff0c;网站可用性的基础保障之一&#xff0c;这里将对应的概念知识和实操步骤进行整理与收集。 1、基础概念详解 1.1、高可用集群 高可用集群&#xff08;High Availability Cluster&#xff0c;简称HA Cluster&am…

用友U9-UBF自定义报表-打印模板开发学习笔记

自定义报表、打印模板开发学习笔记 一、基础了解 1、UBF开发工具的了解 Ideconfig.xml配置 True&#xff1a;打印、报表设计模式 False&#xff1a;单据设计模式 2、开发环境试用 BE&#xff1a;实体项目 BF&#xff1a;操作项目 SV&#xff1a;服务项目 分析项目&am…

NGINX_六 nginx 日志文件详解

六 nginx 日志文件详解 nginx 日志文件分为 **log_format** 和 **access_log** 两部分log_format 定义记录的格式&#xff0c;其语法格式为log_format 样式名称 样式详情配置文件中默认有log_format main $remote_addr - $remote_user [time_local] "req…

jQuery 基本操作

01-简介 jQuery 是一个功能丰富且广泛使用的 JavaScript 库&#xff0c;它简化了 HTML 文档遍历和操作、事件处理、动画和 Ajax 操作。jQuery 通过其易用的 API&#xff0c;使复杂的 JavaScript 编程任务变得更加简单&#xff0c;并且兼容各种浏览器。 1、jQuery特点 简化 DOM …

【Mac】Pixelmator Pro for Mac(媲美PS的修图软件)软件介绍

软件介绍 Pixelmator Pro是一款功能强大的图像编辑软件&#xff0c;专为macOS平台设计。它结合了丰富的图像编辑功能和直观的用户界面&#xff0c;适合专业摄影师、设计师以及图像编辑爱好者。以下是Pixelmator Pro的一些主要特点和功能介绍&#xff1a; 功能特色 非破坏性编…

MSPM0G3507——创建新的.c.h文件

在项目处点击右键&#xff0c;再点击New File 再命名.c.h即可

JavaWeb——MySQL:DML对表数据的修改

2.DML对表数据的修改 2.1 修改表的数据 (1) 修改单行单列 SQL语句&#xff1a;update 表名 set 列名1数值1 where 列名2数值2&#xff1b; 将sql_student表姓名为吕小布的那行&#xff0c;性别设置为女&#xff1b; (2) 修改单行多列 SQL语句&#xff1a;update 表名 set 列…