J.U.C之FutureTask

本文深入解析FutureTask的原理及应用场景,演示了如何利用FutureTask实现异步计算和结果获取,同时介绍了FutureTask与线程池结合使用的方法,以及如何通过FutureTask实现任务取消。此外,还提供了一个基于FutureTask的缓存计算结果的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇记录一下FutureTask的个人理解

FutureTask可用于异步获取执行结果或取消执行任务的场景。通过传入Runnable或者Callable的任务给FutureTask,直接调用其run方法或者放入线程池执行,之后可以在外部通过FutureTask的get方法异步获取执行结果,因此,FutureTask非常适合用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。另外,FutureTask还可以确保即使调用了多次run方法,它都只会执行一次Runnable或者Callable任务,或者通过cancel取消FutureTask的执行等。

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class FutureTaskTest {


    public static void main(String[] args) throws Exception {
        FutureTask<String> futureTask = new FutureTask(new Callable() {
            public String call() throws Exception {
                System.out.println("futureTask开始做一些事情" + new SimpleDateFormat(" HH:mm:ss").format(new Date()));
                Thread.sleep(5000);
                return "做完了";
            }
        });

        new Thread(futureTask).start();
        System.out.println("main线程futureTask启动之后做其他的一些事情" + new SimpleDateFormat(" HH:mm:ss").format(new Date()));
        Thread.sleep(2000);//main线程睡眠2秒  表示做其他事情需要的时间
        /**
         * 下面获取futureTask的线程去做的事情的结果
         * 如果futureTask没有执行完
         * 那么程序会一直阻塞在这里
         * 直到futureTask执行完成之后  才会继续往下执行
         */
        String res = futureTask.get();
        System.out.println("futureTask的执行结果是:" + res + "   " + new SimpleDateFormat(" HH:mm:ss").format(new Date()));
    }

}

上面这段代码 演示了futureTask的基本使用方式 他的执行结果是:

main线程futureTask启动之后做其他的一些事情 17:54:53
futureTask开始做一些事情 17:54:53
futureTask的执行结果是:做完了    17:54:58

从上面这个执行结果可以看出来,当程序启动后,main线程和 futureTask各自开始执行,5秒之后输出了futureTask的执行结果。
这可以体现出,futureTask可以拿到线程执行的结果,如果futureTask.get() 的时候 futureTask和没有执行完成,那么程序就会一直阻塞,知道futureTask执行完成之后才会继续开始往下执行。

补充一个《java并发编程实战》第5章的例子:
这个例子使用FutureTask处理了一个缓存计算结果的功能:

Computable类:

public interface Computable<A, V> {
    V compute(A arg) throws InterruptedException;
}

ExpensiveFuntion类:

import java.math.BigInteger;

public class ExpensiveFuntion implements Computable<String, BigInteger> {

    @Override
    public BigInteger compute(String arg) throws InterruptedException {
        //做一些耗时的处理
        return new BigInteger(arg);
    }
}

Memoizer类:

import java.util.concurrent.*;

public class Memoizer<A, V> implements Computable<A, V>{

    private final ConcurrentHashMap<A, Future<V>> cache = new ConcurrentHashMap<A, Future<V>>();

    private final Computable<A, V> c;

    public Memoizer(Computable<A, V> c) {
        this.c = c;
    }

    @Override
    public V compute(final A arg) throws InterruptedException {
        while (true){
            Future<V> f = cache.get(arg);                               //先看是不是已经缓存过了处理结果
            if(f == null){                                              //处理结果如果为空
                Callable<V> eval = new Callable<V>() {
                    @Override
                    public V call() throws InterruptedException {
                        return c.compute(arg);
                    }
                };
                FutureTask<V> ft = new FutureTask<>(eval);              //将任务放入FutureTask准备执行
                f = cache.putIfAbsent(arg, ft);                         //把任务放入ConcurrentHashMap  使用的是putIfAbsent
                if(f == null) {
                    f = ft;
                    ft.run();                                           //开始执行  这里将会调用c.compute()
                }
            }
            try{
                return f.get();                                         //如果计算完成   那么将返回处理结果
            } catch (CancellationException e){
                cache.remove(arg, f);                                   //捕获CancellationException的话说明处理被取消,那么移除无效的缓存
            } catch (ExecutionException e){
                throw launderThrowable(e.getCause());
            }
        }
    }

}

这里只是把《java并发编程实战》的代码贴出来,写了一些注释,感兴趣的可以去这本书的第5章第6小节开始看

个人浅薄理解,欢迎补充

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值