适配器模式之FutureTask

最近在学习JUC的相关类的源码的时候,看到了FutrueTask类中有使用到适配器模式,加之前段时间刚学习了设计模式,所以就了解了一下加深对适配器模式的理解。

简单解释一下适配器的思想:就是一个类不能被直接使用,就通过适配器将其转换为另一个类的过程。就像家庭电压为220V,但是手机充电是不能直接使用220V的交流电,需要通过电源适配器将其转换为5V的直流电才能直接使用,这个电源适配器就是适配器模式中的适配器。

直接上代码:

构造方法一:传入参数为Callable接口

    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }

构造方法二:传入的参数为Runnable接口

	// 这是FutureTask的构造方法
    public FutureTask(Runnable runnable, V result) {
    	// 调用Executors类中的callable方法进行转化
        this.callable = Executors.callable(runnable, result);
        this.state = NEW;       // ensure visibility of callable
    }

看到Executors中 的方法

	// Executors类中的callable方法
    public static <T> Callable<T> callable(Runnable task, T result) {
        if (task == null)
            throw new NullPointerException();
        // 返回类型是Callable
        // 这里就开始使用适配器模式了
        return new RunnableAdapter<T>(task, result);
    }

在Executors中有一个内部类:即我们的适配器类

	// 实现了Callable接口
    static final class RunnableAdapter<T> implements Callable<T> {
        final Runnable task;
        final T result;
        // 传入Runnable接口(实现类)和返回值
        RunnableAdapter(Runnable task, T result) {
            this.task = task;
            this.result = result;
        }
        // 实现call()方法
        public T call() {
        	// 在call方法中调用Runnable实现类中的run()方法
        	// 变相实现了将Runnable转化为Callable的过程
            task.run();
            // 返回值(Callable接口的call方法有返回值)
            return result;
        }
    }

可以看到关键类RunnableAdapter类实现了一个巧妙的转换就将Runnable封装成了Callable。
同时可以看到这里使用的是类适配器模式,因为直接实现了Callable接口。(另外有对象适配器模式等)。
通过这么一个简单案例可以加深对适配器模式的理解。

<think>嗯,用户想了解A cancellable asynchronous computation,也就是FutureTask。我需要先回忆一下Java并发相关的知识。FutureTaskJava中的一个类,属于java.util.concurrent包。用户提到它作为可取消的异步计算基类,实现了Future接口,对吧。 首先,用户的问题可能来自实际开发中需要处理异步任务,并希望了解如何控制这些任务的执行,比如取消任务或者获取结果。可能用户在使用多线程时遇到了需要管理任务生命周期的需求,所以才会关注FutureTask的特性。 接下来,用户提供的资料里提到FutureTask提供了启动和取消计算的方法,查询任务是否完成,以及获取结果。结果只能在任务完成后获取,否则get方法会阻塞。任务完成后不能重启或取消,除非使用runAndReset。这需要解释清楚这几个关键点。 用户还提到FutureTask可以包装Callable或Runnable,并且因为实现了Runnable,所以可以提交给Executor执行。这部分可能需要举例说明如何使用,比如用Callable创建任务,然后提交到线程池。 另外,用户资料里提到除了作为独立类,还提供protected方法,方便创建自定义任务类。这部分可能需要说明如何继承FutureTask并利用这些受保护的方法进行扩展。 用户可能需要一个结构清晰的回答,逐步解释FutureTask的作用、使用场景、主要方法以及注意事项。可能需要分点说明,比如核心特性、使用方式、注意事项、示例代码等。同时,要确保符合用户给的系统级指令,比如正确使用LaTeX格式,行内公式用$...$,独立公式用$$...$$,不过在这个问题中可能数学公式较少,但如果有涉及的话要注意格式。 需要检查用户是否可能混淆了Future和FutureTask,需要明确两者的关系:FutureTask是Future的一个实现类,增强了功能。同时,要强调其可取消的特性,以及与其他并发工具(如ExecutorService)的配合使用。 可能需要注意用户提到的runAndReset方法,这是FutureTask的一个特殊方法,允许任务完成后重置状态再次执行,但一般情况下任务只能执行一次。这部分可能需要特别说明,避免用户误用。 最后,用户可能需要一个代码示例来更好地理解如何使用FutureTask,比如创建实例、提交到线程池、取消任务、获取结果等步骤。同时要提醒异常处理和线程安全的问题。 总结回答结构:先介绍FutureTask的定义和作用,然后分核心特性、使用方式、注意事项、示例等部分详细说明。确保使用中文,语言清晰,技术点准确,符合用户的要求。</think>以下是对`FutureTask`的详细介绍: ### 一、核心概念 `FutureTask`是Java并发库(`java.util.concurrent`)中一个实现`Future`接口的类,用于表示**可取消的异步计算任务**。其特点包括: 1. 包装`Callable`或`Runnable`对象,支持异步执行 2. 提供任务状态查询(完成/取消) 3. 通过阻塞方式获取计算结果 ### 二、核心特性 1. **任务生命周期控制** - 启动:通过`run()`方法或提交到线程池(`Executor`)执行 - 取消:`cancel(boolean mayInterruptIfRunning)`方法 - 状态查询:`isDone()`、`isCancelled()` 2. **结果获取机制** - `get()`方法会阻塞直到任务完成 - 超时控制:`get(long timeout, TimeUnit unit)` 3. **特殊方法** - `runAndReset()`:执行任务后重置状态,允许重复执行(需重写) ### 三、使用方式 ```java // 示例:使用Callable创建任务 Callable<Integer> task = () -> { TimeUnit.SECONDS.sleep(2); return 42; }; FutureTask<Integer> futureTask = new FutureTask<>(task); ExecutorService executor = Executors.newSingleThreadExecutor(); executor.submit(futureTask); // 取消任务(如果未完成) futureTask.cancel(true); // 获取结果 if(!futureTask.isCancelled()) { Integer result = futureTask.get(); } ``` ### 四、类继承关系 $$ \begin{array}{ccc} & \text{Runnable} & \\ & \uparrow\text{implements} & \\ \text{FutureTask} & \rightarrow & \text{Future} \\ \end{array} $$ ### 五、设计模式应用 1. **适配器模式**:将`Runnable`适配为`Callable` 2. **保护性暂停模式**:通过`get()`方法实现结果等待 ### 六、注意事项 1. **一次性执行**:标准模式下任务不可重启(除非使用`runAndReset()`) 2. **线程安全**:内部通过CAS操作保证状态原子性 3. **异常处理**:任务中未捕获的异常会在调用`get()`时抛出`ExecutionException` ### 七、扩展应用 可通过继承`FutureTask`并重写以下方法实现定制: ```java protected void done() { /* 任务完成时回调 */ } protected void set(V v) { /* 自定义结果设置逻辑 */ } protected void setException(Throwable t) { /* 自定义异常处理 */ } ``` ### 八、性能优化建议 1. 优先使用`CompletableFuture`(Java 8+) 2. 避免长时间阻塞`get()`方法 3. 配合线程池使用时应考虑任务拒绝策略 (注:文中代码示例遵循Java语法规范,实际使用时需处理`InterruptedException`和`ExecutionException`)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值