Callable, Future和FutureTask简述

JDK1.5后新增了一些接口用于并发编程的接口,Callable,Future。以及1.6添加了FutureTask。之前看到了他们的使用,JDK1.8还添加了CompletableFuture,一直想了解一下这些东西。这里记录下对Callable, Future和FutureTask的理解。

相关接口

FutureTask实现了RunnableFuture接口,而RunnableFuture继承了Runnable,Future接口。FutureTask又有一个Callable参数的构造函数,下面分别介绍这些接口。

Runnable

这个是在Java一开始就出现了的接口,只有一个接口方法run,表示可以被运行的类。可以放到线程池,Thread中运行。跟Thread是两种不同的实现方式。

Future

这是在JDK1.5新增的接口,展示异步执行的结果(结果,将来的,Future)。他有以下几个方法:

  • cancel: 尝试去取消这个任务,如果该任务已经完成,或者已经取消,或者其他什么原因将不能取消。
  • get: 可以通过get方法获取异步线程的结果,如果没有执行完成则阻塞当前线程,等待异步线程执行完获取结果。
  • isDone: 判断该任务是否已经完成。如果是被取消,中断等,该方法也会返回true。
  • isCancelled: 判断该任务是否已经取消。

Runnable和Thread都有一个问题,就是不能够直接获取异步线程运行的结果,而Future可以做到。

RunnableFuture

实现了Runnable接口和Future接口。

Callable

一个可以返回结果的接口。只有一个方法call。

使用范例

使用Callable放到线程池中运行。

public class TestFuture {
    public static void main(String[] args) throws InterruptedException, ExecutionException{
        ExecutorService executor = Executors.newCachedThreadPool();
        Task task = new Task();
        Future<Integer> future = executor.submit(task);
        // do something
        System.out.println("可以先做一些事情,再去获取运行结果");
        if(!future.isDone()){
            // you also can do something.
        }
        System.out.println("运行结果: "+future.get()); // 可能会阻塞等待结果
    }

    static class Task implements Callable<Integer>{

        @Override
        public Integer call() throws Exception {
            System.out.println("异步任务开始运行");
            TimeUnit.SECONDS.sleep(3);
            int sum = 0 ;
            for(int i = 0 ; i != 200; ++i){
                sum+=i;
            }
            System.out.println("异步任务完成运行");
            return sum;
        }

    }
}
//运行结果
/*
可以先做一些事情,再去获取运行结果
异步任务开始运行
异步任务完成运行
运行结果: 19900
*/

可以自己实现Callable接口,Executor执行完成后会返回一个Future对象。在获取运行结果前,可以先做一些其他的事情。

使用FutureTask

public class TestFutureTask {
    public static void main(String[] args) throws InterruptedException, ExecutionException{
        ExecutorService executor = Executors.newCachedThreadPool();
        FutureTask<Integer> futureTask = new FutureTask<Integer>(new Task());
        executor.submit(futureTask); //调用的submit(Runnable runnable) 方法
        // do something
        System.out.println("可以先做一些事情,再去获取运行结果");
        if(!futureTask.isDone()){
            // you also can do something.
        }
        System.out.println("运行结果: "+futureTask.get()); // 可能会阻塞等待结果
    }


    static class Task implements Callable<Integer>{

        @Override
        public Integer call() throws Exception {
            System.out.println("异步任务开始运行");
            TimeUnit.SECONDS.sleep(3);
            int sum = 0 ;
            for(int i = 0 ; i != 200; ++i){
                sum+=i;
            }
            System.out.println("异步任务完成运行");
            return sum;
        }

    }
}

跟前面直接使用Callable结果是一样的,只是使用方式有点不一样。这里不需要从submit中获得Future对象,直接就是传入的那个参数futureTask,在有些使用使用起来会更加方便。

总结

我觉得Future接口提供了一种异步操作新的思路,Runnable和Thread都是直接执行完就没有了,并没有获得执行结果的接口,但是Future可以获得执行结果。Future就是用来展示执行结果。当然Future这一系列接口的使用远远不止这些,Future的get方法还可以设置超时时间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值