1.接口的定义:

public interface Callable<V>
{   V call() throws Exception;
} 
  • 1
  • 2
  • 3
  • 4

2.Callable和Runnable的异同

先看下Runnable接口的定义

public interface Runnable {public abstract void run();
}
  • 1
  • 2
  • 3

Callable的call()方法类似于Runnable接口中run()方法,都定义任务要完成的工作,实现这两个接口时要分别重写这两个方法,主要的不同之处是call()方法是有返回值的(其实还有一些区别,例如call方法可以抛出异常,run方法不可以),运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。

3. Callable类型的任务可以有两种执行方式:

我们先定义一个Callable任务MyCallableTask:

class MyCallableTask implements Callable<Integer>{@Overridepublic Integer call() throws Exception {System.out.println("线程在进行计算");Thread.sleep(3000);int sum = 0;for(int i=0;i<100;i++)sum += i;return sum;}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

①借助FutureTask执行 
FutureTask类同时实现了两个接口,Future和Runnable接口,所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。

借助FutureTask执行的大体流程是:

Callable<Integer> mycallabletask = new MyCallableTask();
FutureTask<Integer> futuretask= new FutureTask<Integer>(mycallabletask);
new Thread(futuretask).start();
  • 1
  • 2
  • 3

通过futuretask可以得到MyCallableTask的call()的运行结果: 
futuretask.get(); 
②借助线程池来运行 
线程池中执行Callable任务的原型例如:

public interface ExecutorService extends Executor {//提交一个Callable任务,返回值为一个Future类型<T> Future<T> submit(Callable<T> task);//other methods...}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

借助线程池来运行Callable任务的一般流程为:

  ExecutorService exec = Executors.newCachedThreadPool();Future<Integer> future = exec.submit(new MyCallableTask());
  • 1
  • 2

通过future可以得到MyCallableTask的call()的运行结果: 
future.get(); 
在网上看到了几个比较好的代码例子: 
a.Callable任务借助FutureTask运行:

public class CallableAndFutureTask {public static void main(String[] args) {Callable<Integer> callable = new Callable<Integer>() {public Integer call() throws Exception {return new Random().nextInt(100);}};FutureTask<Integer> future = new FutureTask<Integer>(callable);new Thread(future).start();try {Thread.sleep(5000);System.out.println(future.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

b.Callable任务和线程池一起使用,然后返回值是Future:

public class CallableAndFuture {public static void main(String[] args) {ExecutorService threadPool = Executors.newSingleThreadExecutor();Future<Integer> future = threadPool.submit(new Callable<Integer>() {public Integer call() throws Exception {return new Random().nextInt(100);}});try {Thread.sleep(5000);// 可能做一些事情System.out.println(future.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

以上a,b例子摘自(http://blog.csdn.net/ghsau/article/details/7451464) 
c.当执行多个Callable任务,有多个返回值时,我们可以创建一个Future的集合,例如:

class MyCallableTask implements Callable<String> {private int id;  public OneTask(int id){  this.id = id;  }  @Override  public String call() throws Exception {  for(int i = 0;i<5;i++){System.out.println("Thread"+ id);  Thread.sleep(1000); }  return "Result of callable: "+id;  }
}
public class Test {   public static void main(String[] args) {  //Callable<String> mycallabletask = new MyCallableTask(1);  ExecutorService exec = Executors.newCachedThreadPool();    ArrayList<Future<String>> results = new ArrayList<Future<String>>();      for (int i = 0; i < 5; i++) {    results.add(exec.submit(new MyCallableTask(i)));    }    for (Future<String> fs : results) {    if (fs.isDone()) {    try {  System.out.println(fs.get());   } catch (Exception e) {  e.printStackTrace();  }  } else {    System.out.println("MyCallableTask任务未完成!");    }    }    exec.shutdown();  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

那么引入Callable接口具有哪些好处呢? 
①可以获得任务执行返回值; 
②通过与Future的结合,可以实现利用Future来跟踪异步计算的结果。

Callable接口解析相关推荐

  1. 【Android 异步操作】FutureTask 分析 ( Future 接口解析 | Runnable 接口解析 | Callable 接口解析 )

    文章目录 一.Future 接口 1.Future 接口简介 2.取消任务方法 3.Future 接口源码注释 二.Callable 接口 三.Runnable 接口 上一篇博客 [Android 异 ...

  2. 【高并发】深入解析Callable接口

    本文纯干货,从源码角度深入解析Callable接口,希望大家踏下心来,打开你的IDE,跟着文章看源码,相信你一定收获不小. 1.Callable接口介绍 Callable接口是JDK1.5新增的泛型接 ...

  3. 创建线程的第三种方式:实现Callable接口(含部分源码解析)

    创建线程的第三种方式--实现Callable接口 package com.lqy.Multithreading; import java.util.concurrent.Callable; impor ...

  4. 从源码角度详解Java的Callable接口

    摘要:本文从源码角度深入解析Callable接口. 本文分享自华为云社区<深入解析Callable接口>,作者: 冰 河 . 本文纯干货,从源码角度深入解析Callable接口,希望大家踏 ...

  5. 一个Callable接口能有多少知识点?在裁员的大背景下,我仍然吊打了大厂面试官

    大家好,我是冰河~~ 并发编程一直是程序员们比较头疼的,如何编写正确的并发程序相比其他程序来说,是一件比较困难的事情,并发编程中出现的 Bug 往往也是特别诡异的. 之所以说并发编程出现的 Bug 比 ...

  6. Java多线程 - Runnable接口和Callable接口的区别

    文章目录 1. Runnable接口实例 2. Callable接口原理 3. Callnable接口实例 4. FutureTask是什么? 5. 线程池中 submit() 和 execute() ...

  7. 三种创建线程方式之Callable接口

    一.类继承关系及API解析 Callable接口 @FunctionalInterface public interface Callable<V> {V call() throws Ex ...

  8. java.util.concurrent.Callable 接口 源码

    2019独角兽企业重金招聘Python工程师标准>>> 线程池相关 源码: package java.util.concurrent;@FunctionalInterface pub ...

  9. Java多线程之Callable接口的实现

    import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.ut ...

最新文章

  1. java ascii 编码方式_JAVA 的ASCII字符编码一览表
  2. SNMP在windows linux router上的配置笔记
  3. 【错误记录】Oboe / AAudio 播放器报错 ( onEventFromServer - AAUDIO_SERVICE_EVENT_DISCONNECTED - FIFO cleared )
  4. 【bzoj5016】[Snoi2017]一个简单的询问 莫队算法
  5. [ARM异常]-armv8/armv9异步异常类型、路由、屏蔽
  6. python自带编译器闪退_python自带编译器在写入文件时闪退,或者一步步执行到写入时提示8170。解决办法:...
  7. Pandas文本处理双雄extract+extractall
  8. 论文浅尝 | 基于置信度的知识图谱表示学习框架
  9. thinkphp实现当前页面点击下载文件实例
  10. PL/SQL Step By Step(三)
  11. php post 漏洞_漏洞研究|ThinkPHP request函数远程代码执行
  12. CUDA的内存泄露问题及解决办法
  13. 基于python中jieba包的详细使用介绍
  14. c语言课程设计,学生信息管理系统
  15. 浅析redis雪崩击穿和穿透
  16. 易优超级字典生成器 v3.35 下载
  17. 服务器查看GPU及各个参数
  18. ubuntu18.04 HP笔记本合上盖子不休眠不断网
  19. 在win10里修改mysql的root密码
  20. 如何使用EXCEL批量检查地址格式?

热门文章

  1. 网红带货直播,直播带货,在线教育直播,火山抖音娱乐直播中的技术分析---推流与播流
  2. 官方文档:QUX主题使用指南
  3. sap 物料标准价和移动平均价差异
  4. 计算机科学与技术情话,一个专业一句情话,你被哪个专业甜到了?
  5. 页面自动跳转实现方法
  6. html 自动跳转手机版,HTML实现页面自动跳转的五种方法
  7. 大数据开发和java的前景_Java大数据开发前景好吗?
  8. 【hautoj 1285 】 军团再临 【 思维+并查集】
  9. oracle sql查询缺失号,Oracle层次查询和分析函数
  10. macOS fio 命令