FutureTask 使用场景介绍

可以通过其提供的get方法,在FutureTask不同的状态下,以阻塞或者直接返回的方式或者结果。

FutureTask实现了Future和Runnable接口。以FutureTask是否调用了run方法,可以简单分为三种状态

1. 未启动。 run方法未执行。

2. 已启动。 run方法执行。

3. 已完成。 run方法正常执行完毕,或者调用cancel取消,或者run方法执行过程中抛出异常。

 

强调以上不同状态的特性,是为了突出一下这个场景的使用:多线程执行任务,任务只被执行一次

FutureTask正常执行完成会返回值(不会再次执行),若中断,正在中断,或者取消时抛出异常。

看下代码,落地下:

Class TaskHandler{
    // 记录执行过的任务
    private final ConcurrentHashMap<Object,Future<String>> taskCache = new ConcurrentHashMap<Object,Future<String>>// hashet用Collections包装下也可以用,再根据put的返回,判断该任务已经存在。
    public String execute(final String taskName) throws ExecutionException, InterruptException {
        while (true) {
            Future<String> future = taskCache.get(taskName);
            if(future == null) {
                Callable<String> task = new Callable<String>() {
                    @Override
                    public String call() throws InterruptedException{
                        return taskName;
                    }
                };
            FutureTask<String> futureTask = new FutureTask<String>(task);
            future = taskCache.put(taskName, futureTask);
            if(future == null) {
                future = futureTask;
                futureTask.run();
            }
            }
            try {
                future.get();
            } catch(CancellationException e) {
                // 这个是get方法throw出来的异常 这里有两种异常CancellationException ExecutionException 只处理CancellationException,是因为这个异常是主动取消任务的,我们需要将其从taskCache中去除掉
                taskCache.remove(taskName, future);
            }
        }
    }
}

以上代码有个小细节,这里指出一下。taskCache.remove(taskName, future),可不可以用taskCache.remove(taskName)?答案是可以的,前者是找到taskName对应的index后,调用future的equal判断是否是同一个对象,后者通过对taskName指针地址或者hashcode进行判断是否是同一个对象的。推荐使用第二种remove方法,因为String重写了equal和hashcode。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值