美文网首页
Callable、Future和FutureTask

Callable、Future和FutureTask

作者: 湘西刺客王胡子 | 来源:发表于2018-05-25 15:08 被阅读0次

    tags: java concurrent

    Callable接口

     public interface Callable<V> {
        V call() throws Exception;
    }
    
    • java1.1推出了Runnable,而Callable是在java1.5被引入
    • 与Runnable相似,有且仅有一个方法,在java 8时被声明为函数式接口
    • 为了解决Runnable不能从执行中返回结果的问题,产生了Callable,相当于在原有功能上增添了结果返回、取消、异常抛出的功能。
    • 运行一个Callable线程有三种方式,你会得到的对象有两种类型,它们是Future和FutureTask

    Future接口

     interface Future<V> {
    // 获得线程的执行结果
        V get();
    // 定义了等待在当前线程中等待结果的最大时间
        V get(long timeout, TimeUnit unit);
    // 取消任务, 标记mayInterrupt表示如果任务已经开始并且此刻正在运行,那么应该被中断。
        boolean cancel(boolean mayInterruptIfRunning);
    // 检查一个任务是否已经被完成
        boolean isCancelled();
    // 检查任务是否被取消
        boolean isDone();
    }
    
    • Future 可以被看作一个整理存储Callable 计算结果的容器。callable 的计算能持续在另一个线程中, 并且任何获取一个Future 结果的尝试都将被阻塞,并且一旦(结果)变得可用,便会返回结果。

    Future 提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get 方法来获取结果,如果线程没有执行完,Future.get() 方法可能会阻塞当前线程的执行;如果线程出现异常,Future.get() 会 throws InterruptedException 或者 ExecutionException;如果线程已经取消,会跑出 CancellationException。取消由 cancel 方法来执行。isDone 确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。如果为了可取消性而使用 Future 但又不提供可用的结果,则可以声明Future<?> 形式类型,并返回 null 作为底层任务的结果。

    • 使用线程池的commit方法运行一个Callable线程,就可以得到一个Future对象:
        ExecutorService es = Executors.newSingleThreadExecutor();
        Callable<String> task = () -> {return "123"};
        Future<String> result = es.submit(task);
    

    FutureTask

    • FutureTask实现了RunnableFuture接口,而RunnableFuture同时继承了Runnable和Future两个接口
    • FutureTask是Future接口的一个唯一实现类。
    • FutureTask提供了2个构造器:
    public FutureTask(Callable<V> callable) {}
    public FutureTask(Runnable runnable, V result) {}
    
    • 如果只是运行一个简单的Callable线程,不想配置线程池,可使用Callable构造一个FutureTask对象,并放入Thread中进行start()
    • 当然,也可以使用线程池对一个FutureTask对象进行submit()操作
    //第一种方式
    ExecutorService executor = Executors.newCachedThreadPool();
    Callable<String> task = () -> {return "123"};
    FutureTask<Integer> futureTask = new FutureTask<Integer>(task);
    executor.submit(futureTask);
    executor.shutdown();
         
    //第二种方式,注意这种方式和第一种方式效果是类似的,只不过一个使用的是ExecutorService,一个使用的是Thread
    Callable<String> task = () -> {return "123"};
    FutureTask<Integer> futureTask = new FutureTask<Integer>(task);
    Thread thread = new Thread(futureTask);
    thread.start();
    

    总结

    如果你有很多任务要去执行, 并且所有的任务并不依赖前一个的执行结果, 如果你的计算机允许, 你可以使用多线程使用多个处理器同时处理所有的工作。这能够使你的程序执行的更快。

    相关文章

      网友评论

          本文标题:Callable、Future和FutureTask

          本文链接:https://www.haomeiwen.com/subject/rgwdjftx.html