Callable接口解析
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接口解析相关推荐
- 【Android 异步操作】FutureTask 分析 ( Future 接口解析 | Runnable 接口解析 | Callable 接口解析 )
文章目录 一.Future 接口 1.Future 接口简介 2.取消任务方法 3.Future 接口源码注释 二.Callable 接口 三.Runnable 接口 上一篇博客 [Android 异 ...
- 【高并发】深入解析Callable接口
本文纯干货,从源码角度深入解析Callable接口,希望大家踏下心来,打开你的IDE,跟着文章看源码,相信你一定收获不小. 1.Callable接口介绍 Callable接口是JDK1.5新增的泛型接 ...
- 创建线程的第三种方式:实现Callable接口(含部分源码解析)
创建线程的第三种方式--实现Callable接口 package com.lqy.Multithreading; import java.util.concurrent.Callable; impor ...
- 从源码角度详解Java的Callable接口
摘要:本文从源码角度深入解析Callable接口. 本文分享自华为云社区<深入解析Callable接口>,作者: 冰 河 . 本文纯干货,从源码角度深入解析Callable接口,希望大家踏 ...
- 一个Callable接口能有多少知识点?在裁员的大背景下,我仍然吊打了大厂面试官
大家好,我是冰河~~ 并发编程一直是程序员们比较头疼的,如何编写正确的并发程序相比其他程序来说,是一件比较困难的事情,并发编程中出现的 Bug 往往也是特别诡异的. 之所以说并发编程出现的 Bug 比 ...
- Java多线程 - Runnable接口和Callable接口的区别
文章目录 1. Runnable接口实例 2. Callable接口原理 3. Callnable接口实例 4. FutureTask是什么? 5. 线程池中 submit() 和 execute() ...
- 三种创建线程方式之Callable接口
一.类继承关系及API解析 Callable接口 @FunctionalInterface public interface Callable<V> {V call() throws Ex ...
- java.util.concurrent.Callable 接口 源码
2019独角兽企业重金招聘Python工程师标准>>> 线程池相关 源码: package java.util.concurrent;@FunctionalInterface pub ...
- Java多线程之Callable接口的实现
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.ut ...
最新文章
- java ascii 编码方式_JAVA 的ASCII字符编码一览表
- SNMP在windows linux router上的配置笔记
- 【错误记录】Oboe / AAudio 播放器报错 ( onEventFromServer - AAUDIO_SERVICE_EVENT_DISCONNECTED - FIFO cleared )
- 【bzoj5016】[Snoi2017]一个简单的询问 莫队算法
- [ARM异常]-armv8/armv9异步异常类型、路由、屏蔽
- python自带编译器闪退_python自带编译器在写入文件时闪退,或者一步步执行到写入时提示8170。解决办法:...
- Pandas文本处理双雄extract+extractall
- 论文浅尝 | 基于置信度的知识图谱表示学习框架
- thinkphp实现当前页面点击下载文件实例
- PL/SQL Step By Step(三)
- php post 漏洞_漏洞研究|ThinkPHP request函数远程代码执行
- CUDA的内存泄露问题及解决办法
- 基于python中jieba包的详细使用介绍
- c语言课程设计,学生信息管理系统
- 浅析redis雪崩击穿和穿透
- 易优超级字典生成器 v3.35 下载
- 服务器查看GPU及各个参数
- ubuntu18.04 HP笔记本合上盖子不休眠不断网
- 在win10里修改mysql的root密码
- 如何使用EXCEL批量检查地址格式?