我们原来所说的继承Thread或者实现Runnable的方式都无法获得线程的执行结果,除非使用共享变量或者线程通信,我们先看一下Runnable接口的源码:

public interface Runnable{public abstract void run(){}
}
复制代码

run()的返回值为void,在任务执行完之后没有返回

继承Thread和实现Runnable这两种方式,都无法获得线程执行的结果

Callable可以弥补这一个缺点:

public interface Callable<V>{V call() throws Exception
}复制代码

是一个泛型接口,返回值类型为传入进来的的T类型的值

注意:Callable中方法是call而不是run

使用Callable

一般配合ExecutorService来使用:

其中声明了若干个重载的submit方法

<T> Future<T> submit(Callable<T> task);<T> Future<T> submit(Runnable task, T result);    //一般不使用Future<?> submit(Runnable task);
复制代码

Future

Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果

public interface Future<V> {boolean cancel(boolean mayInterruptIfRunning);boolean isCancelled();boolean isDone();V get() throws InterruptedException, ExecutionException;V get(long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException;}复制代码

cancel:取消任务

mayInterruptIfRunning:是否可以取消正在执行的任务

isCancelled:是否成功取消

isDone:是否已经完成

get:获取执行结果,一直等到任务执行完毕才返回,阻塞等待

get(long timeout, TimeUint unit):用来获取执行结果,指定时间内,还没有获取到结果,就返回null

也就是说Future用于异步获取执行结果或取消执行任务提供了三种功能:

  1)判断任务是否完成;

  2)能够中断任务;

  3)能够获取任务执行结果。

因为Future只是一个接口,所以是无法直接用来创建对象使用的,因此就有了下面的FutureTask。

FutureTask是Future的唯一实现

public interface RunnableFuture<V> extends Runnbale,Future<V>void run()
}public class FutureTask implements RunnbaleFuture<V>{public FutureTask(Callable<V> callable)public FutureTask(Runnable runnable,V result)
}复制代码

可以看出RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。

这段代码不给答案啦,动手实践感受一下

public class FutureTaskUseDemo {public static void main(String[] agrs) throws InterruptedException, ExecutionException {ExecutorService executor = Executors.newCachedThreadPool();/*** 使用FutureTask的Runnable特性*/Thread thread = new Thread(new FutureTask<>(new BoilWater()));thread.start();/*** 使用FutureTask的Callable特性------第一种写法*/FutureTask futureTask = new FutureTask(new BoilWater());executor.submit(futureTask);out.println("做饭");Thread.sleep(2000);out.println("饭做好了");while (!futureTask.isDone()) {out.println("水还没烧开呢");Thread.sleep(1000);}out.println(futureTask.get());/*** 使用FutureTask的Callable特性------第二种写法*/Future<String> submit = executor.submit(new BoilWater());out.println("做饭");Thread.sleep(2000);out.println("饭做好了");while (!submit.isDone()) {out.println("水还没烧开呢");Thread.sleep(1000);}out.println(submit.get());/*** 多个任务同时并行*/CompletionService<Integer> cs = new ExecutorCompletionService<Integer>(executor);for (int i = 0; i < 5; i++) {final int taskId = i;cs.submit(() -> taskId);}for (int i = 0; i < 5; i++) {try {out.println(cs.take().get());} catch (Exception e) {}}}
}class BoilWater implements Callable<String> {@Overridepublic String call() throws Exception {Thread.sleep(5000);return System.currentTimeMillis() + " 水烧开了";}
}
复制代码

并发-9-Callable和Future相关推荐

  1. 15、Java并发编程:Callable、Future和FutureTask

    Java并发编程:Callable.Future和FutureTask 在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一 ...

  2. futuretask java 并发请求_Java并发编程:Callable、Future和FutureTask

    Java并发编程:Callable.Future和FutureTask 在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一 ...

  3. futuretask java 并发请求_Java并发机制(9)--Callable、Future、FutureTask的使用

    Java并发编程:Callable.Future.FutureTask的使用 继承关系: 1.接口Callable与Runnable 1.1.Runnable接口中只有一个void run()方法,其 ...

  4. 【Java并发】Runnable、Callable、Future、FutureTask

    创建线程的两种方式 直接继承 Thread 实现 Runnable 接口 这两种方式都有一个缺点:在执行完成任务之后,无法直接获取到最后的执行结果.如果需要获取执行结果,就必须通过共享变量或线程通信的 ...

  5. Java高并发编程:Callable、Future和FutureTask

    1. Callable 泛型接口,用于获取线程执行完的结果,Callable的声明如下 public interface Callable<V> {// 返回 V 类型的结果V call( ...

  6. futuretask java 并发请求_【Java并发】Runnable、Callable、Future、FutureTask

    创建线程的两种方式 直接继承 Thread 实现 Runnable 接口 这两种方式都有一个缺点:在执行完成任务之后,无法直接获取到最后的执行结果.如果需要获取执行结果,就必须通过共享变量或线程通信的 ...

  7. Java并发编程:Callable、Future和FutureTask

    在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果. 如果需要获取执行结果,就 ...

  8. 一次搞懂 Runnable、Callable、Future、FutureTask,不懂不要钱!

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 一般创建线程只有两种方式,一种是继承Thread,一种是实 ...

  9. Callable和Future

    接着上一篇继续并发包的学习,本篇说明的是Callable和Future,它俩很有意思的,一个产生结果,一个拿到结果.         Callable接口类似于Runnable,从名字就可以看出来了, ...

  10. Callable和Future、FutureTask的使用

    http://www.silencedut.com/2016/06/15/Callable%E5%92%8CFuture%E3%80%81FutureTask%E7%9A%84%E4%BD%BF%E7 ...

最新文章

  1. 1126 Eulerian Path
  2. (六)java多线程之ReadWriteLock
  3. 警告:攻击者利用 SonarQube 漏洞盗取国内多个机构的大量源码!
  4. angularjs与PHP,我应该混合AngularJS与PHP框架吗?
  5. oracle M4,oracle高级部分 - osc_9gm4ypss的个人空间 - OSCHINA - 中文开源技术交流社区...
  6. Sublime Text 关闭自动更新
  7. 前端学习(568):元素定高 容器定高 为什么不能居中
  8. hibernate和struts实现分页
  9. Warning:mailcious javascript detected on this domain来由
  10. matlab信源编码,常见无失真信源编码算法及Matlab实现比较(27页)-原创力文档
  11. CAD的菜单栏消失,如何再次调出来
  12. button加下划线
  13. 注册表中shell文件不见了_win10系统注册表中的shell文件不小心被删除的恢复教程...
  14. 今日头条的排名算法_今日头条旗下悟空问答的排名算法规则
  15. hbase 0.98.1集群安装
  16. 你是否知到西游记中孙悟空的师傅是什么人?
  17. 智能无感验证实战案例:神州优车
  18. 使用 LaTeX 的笔记
  19. SAP MM02主数据维护多语言长文本,丢失空格的解决办法
  20. Freemarker使用mht制作导出word模板

热门文章

  1. Ubuntu系统在VMware虚拟机中显示显示过小
  2. COALESCE在SQL拼接中的大用途
  3. document.getElementById()和document.forms[0].submit()
  4. 一分钟学会spring注解之@Scope注解
  5. C# 检测文件是否被其他进程占用
  6. mysql字段类型、范围详解
  7. 边看chromium的代码,边想骂人...
  8. 《ASP.NET 开发从入门到精通》----2.3 编译和部署ASP.NET程序
  9. RealPlayer 15正式发布 简体中文版下载
  10. MSDynamicsAX2009成本处理与重估(中文)