当前位置: 首页 > article >正文

Callable

一、Callable 接口定义
@FunctionalInterface
public interface Callable<V> {V call() throws Exception; // 返回类型为泛型V,可抛出异常
}

二、基本使用步骤
1. 定义 Callable 任务
// 示例1:计算两个数的和
Callable<Integer> sumTask = new Callable<>() {@Overridepublic Integer call() throws Exception {return 1 + 2;}
};// 示例2:Lambda简化写法(推荐)
Callable<Integer> sumTask = () -> 1 + 2;
2. 提交任务到线程池
// 创建线程池
ExecutorService executor = Executors.newFixedThreadPool(2);// 提交任务,返回Future对象
Future<Integer> future = executor.submit(sumTask);
3. 通过 Future 获取结果
try {Integer result = future.get(); // 阻塞直到任务完成System.out.println("结果:" + result); // 输出:3
} catch (InterruptedException | ExecutionException e) {e.printStackTrace();
} finally {executor.shutdown(); // 关闭线程池
}

三、Future 核心方法详解
方法作用
V get()阻塞等待任务完成,返回结果。
V get(long timeout, TimeUnit unit)阻塞最多指定时间,超时抛出 TimeoutException
boolean isDone()检查任务是否完成(包括正常结束、异常终止或取消)。
boolean cancel(boolean mayInterrupt)尝试取消任务:若任务未开始,直接取消;若运行中,mayInterrupt=true 会尝试中断。

示例:设置超时和取消任务

Future<Integer> future = executor.submit(() -> {Thread.sleep(3000); // 模拟耗时操作return 100;
});try {Integer result = future.get(1, TimeUnit.SECONDS); // 等待1秒
} catch (TimeoutException e) {System.out.println("任务超时");future.cancel(true); // 中断任务
}

四、处理异常

Callable 抛出的异常会被封装到 ExecutionException 中,需通过 getCause() 获取原始异常:

Callable<Integer> errorTask = () -> {throw new IOException("模拟IO异常");
};Future<Integer> future = executor.submit(errorTask);try {future.get();
} catch (ExecutionException e) {Throwable cause = e.getCause();if (cause instanceof IOException) {System.err.println("捕获到IO异常: " + cause.getMessage());}
}

五、批量提交任务
1. invokeAll:提交多个任务,统一获取结果
List<Callable<Integer>> tasks = Arrays.asList(() -> 1 + 1,() -> 2 + 2,() -> 3 + 3
);List<Future<Integer>> futures = executor.invokeAll(tasks);for (Future<Integer> f : futures) {System.out.println(f.get()); // 输出:2, 4, 6
}
2. invokeAny:提交多个任务,返回第一个完成的结果
Integer result = executor.invokeAny(Arrays.asList(() -> { Thread.sleep(2000); return 10; },() -> { Thread.sleep(1000); return 20; } // 该任务更快完成
));System.out.println(result); // 输出:20

六、使用 FutureTask 直接启动任务

FutureTask 实现了 RunnableFuture,可直接通过 Thread 或线程池执行:

Callable<Integer> task = () -> 5 * 5;
FutureTask<Integer> futureTask = new FutureTask<>(task);// 方式1:通过Thread启动
new Thread(futureTask).start();
System.out.println(futureTask.get()); // 输出:25// 方式2:提交到线程池
executor.submit(futureTask);

七、线程池管理注意事项
  1. 关闭线程池
    使用 shutdown()shutdownNow() 避免资源泄漏:

    executor.shutdown(); // 等待所有任务完成
    // executor.shutdownNow(); // 立即终止所有任务
    
  2. 选择线程池类型

    • newCachedThreadPool:适合短任务,自动回收空闲线程。
    • newFixedThreadPool:固定线程数,适合长期任务。
    • newScheduledThreadPool:支持定时任务。

八、高级用法
1. 结合 Lambda 表达式简化代码
executor.submit((Callable<String>) () -> "Hello, Callable");
2. 使用 CompletableFuture(JDK 8+)

Callable 转换为 CompletableFuture 实现链式调用:

CompletableFuture.supplyAsync(() -> {// 模拟计算return 100;
}, executor).thenAccept(result -> {System.out.println("结果:" + result);
});

九、完整代码示例
import java.util.concurrent.*;public class CallableDemo {public static void main(String[] args) {ExecutorService executor = Executors.newFixedThreadPool(2);// 提交任务Future<Integer> future = executor.submit(() -> {Thread.sleep(1000);return 1 + 2;});try {// 设置超时并获取结果Integer result = future.get(2, TimeUnit.SECONDS);System.out.println("结果:" + result);} catch (TimeoutException e) {System.err.println("任务超时");} catch (ExecutionException e) {System.err.println("任务异常:" + e.getCause());} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {executor.shutdown();}}
}
http://www.lryc.cn/news/2384461.html

相关文章:

  • Honeywell 05701-A-0302 单通道控制卡
  • 爱普生晶振赋能UWB汽车数字钥匙,解锁未来出行新方式
  • 电子电路:深入理解电磁耦合的定义与应用
  • 宝塔安装的 MySQL 无法连接的情况及解决方案
  • 今日行情明日机会——20250523
  • 微服务项目->在线oj系统(Java版 - 4)
  • ReAct 与 CoAct:AI 代理的推理与行动之旅
  • 电子电路:什么是滤波器,什么优势高通滤波器?
  • uni-app使用大集
  • [Spring Boot]整合Java Mail实现Outlook发送邮件
  • 零件剖切配置教学 | 玩转EasyTwin 工业产线第三期(上)课程回顾
  • onnx模型转入rknn3399平台上工作记录
  • 进考场!软考考试现场答题的注意事项
  • 第三个小程序动工:一款结合ai的菜谱小程序
  • OpenCV CUDA 模块图像过滤------创建一个线性滤波器(Linear Filter)函数createLinearFilter()
  • 广告反作弊都有哪些方法
  • Excel 密码忘记了?巧用PassFab for Excel 解密帮您找回数据!
  • Vue.js教学第十二章:Vue Router实战指南(二)
  • 【前端开发】Uniapp日期时间选择器:实现分钟动态步长设置
  • 跑通Multi-Agent-Constrained-Policy-Optimisation
  • Visual Studio已更新为17.14+集成deepseek实现高效编程
  • go 基础语法 【教程 go tour】
  • 养生指南:五维打造健康新方式
  • 网络爬虫学习之httpx的使用
  • 无人机桥梁检测效率问题-高精度3D建模及航线规划
  • 想免费使用 AWS 云服务器?注册、验证及开通全攻略
  • 以太联 - Intellinet 闪耀台北 SecuTech 国际安全科技应用博览会
  • Pandas:数据分析中的缺失值检测、加载、设置、可视化与处理
  • 【Linux系列】EVS 与 VBD 的对比
  • 56 在standby待机打通uart调试的方法