博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java多线程编程之Future/FutureTask和Callable
阅读量:6452 次
发布时间:2019-06-23

本文共 2567 字,大约阅读时间需要 8 分钟。

hot3.png

有这样一种场景,用多线程发送数据到某个服务器,需要知道各个线程是否都发送成功,等所有线程都发送完成才能继续下一轮计算和发送。如果用传统的多线程方式,就需要启动多个线程,然后在每个线程中分别发送数据,外部通过某种方式等待各个线程全部都发送完成,再进行后面的计算等流程。这种实现方式的代码会比较臃肿,在java中提供了一种Callable+Future的方法,可以将异步的多线程调用变为同步方式。

Callable

在java的多线程编程中,有Thread和Runnable两种方式来新建线程,其中Runnable封装了一个异步运行的任务,可以认为是一个没有任何参数和返回值的异步方法。Callable接口类似于Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的,不同之处在于:

Runnable不会返回结果,并且无法抛出经过检查的异常。而Callable是有返回结果并且可能抛出异常的。

Runnable定义了run方法,而Callable定义了一个不带任何参数的叫做call的方法。

此外,Callable接口的类型参数也是返回值的类型。

public interface Callable {

    /**

    * Computes a result, or throws an exception if unable to do so.

    *

    * computed result

    * Exception if unable to compute a result

    */

    V call() throws Exception;

}

Future

Future表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get 方法来获取结果,如有必要,计算完成前可以阻塞此方法。取消则由 cancel 方法来执行。还提供了其他方法,以确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。如果为了可取消性而使用 Future 但又不提供可用的结果,则可以声明 Future<?> 形式类型、并返回 null 作为底层任务的结果。

当使用Future对象时,你就可以启动一个计算,把计算结果给某线程,然后就去干自己的事。Future对象的所有者在结果计算好之后就可以得到它。

public interface Future {

boolean cancel(boolean mayInterruptIfRunning);

boolean isCancelled();

boolean isDone();

V get() throws InterruptedException, ExecutionException;

V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;

}

FutureTask

FutureTask包装器是一种很方便地将Callable转换为Future和Runnable的机制,它同时实现了两者的接口。例如:

Callable comput = …;

FutureTask task = new FutureTask(comput);

Thread t = new Thread(task); // it's a Runnable

t.start();

Integer result = t.get(); // it’s a Future

所以可使用FutureTask包装Callable或Runnable对象。由于FutureTask实现了Runnable,可将 FutureTask提交给线程池的执行器类Executor执行。

使用Future+Callable+ExecutorService的例子

import java.util.ArrayList;

import java.util.List;

import java.util.concurrent.Callable;

import java.util.concurrent.ExecutionException;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.Future;

 

public class FutureTest {

 

  public static class Task implements Callable {

    private long id;

    public Task(long id){

      this.id = id;

    }

 

    @Override

    public String call() throws Exception {

      System.out.printf("Thread#%s : in call\n", this.id);

      return this.id + "";

    }

 }

 

  public static void main(String[] args) throws InterruptedException, ExecutionException {

  List results = new ArrayList();

  ExecutorService execService = Executors.newCachedThreadPool();

    for(int i=0; i<10;i++)

      results.add(execService.submit(new Task(i)));

 

  for(Future res : results)

    System.out.println(res.get());

  }

}

可见,使用Future+Callable模式对于某些需要等待多个线程执行结果的场景非常有用,在HBase的batch操作中就使用了这种模式。

转载于:https://my.oschina.net/sphl520/blog/312486

你可能感兴趣的文章
[转]CMake快速入门教程:实战
查看>>
IntelliJ IDEA创建JavaWeb工程及配置Tomcat部署
查看>>
Markdown用法
查看>>
求最大值及其下标
查看>>
Request header is too large
查看>>
轮播插件swiper.js?
查看>>
网路流24题总结
查看>>
BZOJ-3732 Network 图论 最小生成树 倍增
查看>>
python之文件操作
查看>>
15 个 Android 通用流行框架大全
查看>>
Entity Framwork CodeFirst 学习笔记五:数据库映射的默认配置和设置
查看>>
ant 执行java文件,java文件中含中文,显示乱码
查看>>
IE8兼容@media和mp4视频的解决方案
查看>>
第二周总结
查看>>
ASP.NET完整打包卸载更新攻略(By Installshield 2010)
查看>>
[120_移动开发Android]006_android开发之数据存储之sdcard访问
查看>>
[若有所悟]IT小兵总结IT人特点及挽留IT人才的九大策略
查看>>
概率图模型建模、学习、推理资料总结
查看>>
【转】知道这20个正则表达式,能让你少写1,000行代码
查看>>
自定义 启动和关闭 oracle 的命令
查看>>