FutureTask 使用场景介绍

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

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

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

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

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

 

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

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

看下代码,落地下:

Class TaskHandler{
    // 记录执行过的任务
    private final ConcurrentHashMap> taskCache = new ConcurrentHashMap>// hashet用Collections包装下也可以用,再根据put的返回,判断该任务已经存在。
    public String execute(final String taskName) throws ExecutionException, InterruptException {
        while (true) {
            Future future = taskCache.get(taskName);
            if(future == null) {
                Callable task = new Callable() {
                    @Override
                    public String call() throws InterruptedException{
                        return taskName;
                    }
                };
            FutureTask futureTask = new FutureTask(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。

你可能感兴趣的:(#,java并发,#,android基础)