java线程——详解Callable、Future和FutureTask
回顾:
接上篇博客
java线程——三种创建线程的方式,这篇博客主要介绍第三种方式Callable和Future。比较继承Thread类和实现Runnable接口,接口更加灵活,使用更广泛。但这两种方式都没有返回值,要想返回相应的数据,就要使用Callable和Future方式。
基础:
1、Callable
还是从定义开始,Callable接口有返回值,并且可以抛出异常。
-
/**(有返回值的任务,可能抛出异常)
-
* A task that returns a result and may throw an exception.
-
* Implementors define a single method with no arguments called
-
* {@code call}.
-
-
* @see Executor
-
* @since 1.5
-
* @author Doug Lea
-
* @param <V> the result type of method {@code call}
-
*/
-
@FunctionalInterface
-
public interface Callable<V> {
-
-
V call() throws Exception;
-
}
2、Future
Future同样也是一个接口,主要方法如下,方法的功能比较容易理解,所以就没有写注释。主要作用:获取任务执行结果,中断任务等。
-
package java.util.concurrent;
-
-
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;
-
}
3、FutureTask
-
public class FutureTask<V> implements RunnableFuture<V> {
-
......
-
}
-
-
public interface RunnableFuture<V> extends Runnable, Future<V> {
-
......
-
}
FutureTask实现了RunnableFuture接口,而RunnableFuture接口继承了Runnable和Future。也就是说,它既可以作为Runnable被线程执行,也可以作为Future得到Callable返回值。
使用:
方法一:Callable+Future
-
public class CallableAndFuture {
-
/**
-
* 实现Callable接口
-
*
-
* @author YANG
-
*
-
*/
-
public static class MyCallable implements Callable {
-
-
private int flag = 0;
-
-
public MyCallable(int flag) {
-
-
this.flag = flag;
-
-
}
-
-
// 重写call方法
-
public String call() throws Exception {
-
// 情况一:flag=0 返回0
-
if (this.flag == 0) {
-
-
return "flag = 0";
-
-
}
-
// 情况二:flag=1 返回looping 陷入死循环
-
if (this.flag == 1) {
-
-
try {
-
-
while (true) {
-
-
System.out.println("looping.");
-
-
Thread.sleep(2000);
-
-
}
-
// 情况三:出现异常
-
} catch (InterruptedException e) {
-
-
System.out.println("Interrupted");
-
-
}
-
-
return "false";
-
-
} else {
-
-
throw new Exception("Bad flag value!");
-
-
}
-
-
}
-
-
}
-
-
public static void main(String[] args) {
-
-
// 定义3个Callable类型的任务,构造方法中制定flag的值
-
MyCallable task1 = new MyCallable(0);
-
-
MyCallable task2 = new MyCallable(1);
-
-
MyCallable task3 = new MyCallable(2);
-
-
// 创建一个执行任务的服务
-
-
ExecutorService es = Executors.newFixedThreadPool(3);
-
-
try {
-
-
// 提交并执行任务,任务启动时返回了一个Future对象,
-
-
// 如果想得到任务执行的结果或者是异常可对这个Future对象进行操作
-
-
Future future1 = null;
-
-
future1 = es.submit(task1);
-
-
// 获得第一个任务的结果,如果调用get方法,当前线程会等待任务执行完毕后才往下执行
-
-
System.out.println("task1: " + future1.get());
-
-
Future future2 = es.submit(task2);
-
-
// 等待5秒后,再停止第二个任务。因为第二个任务进行的是无限循环
-
-
Thread.sleep(5000);
-
-
System.out.println("task2 cancel: " + future2.cancel(true));
-
-
// 测试抛出异常
-
-
Future future3 = es.submit(task3);
-
-
System.out.println("task3: " + future3.get());
-
-
} catch (Exception e) {
-
-
System.out.println(e.toString());
-
-
}
-
-
// 停止任务执行服务
-
-
es.shutdownNow();
-
-
}
-
}
执行结果:
方法二:Callable+FutureTask
分析两种方法不同之处就在于Future和FutureTask,其中一个是接口,一个是类。因此,只有main方法调用部分不同,上面的MyCallable类中的内容保持不变。
-
public static void main(String[] args) {
-
-
MyCallable task1 = new MyCallable(0);
-
FutureTask ft1 = new FutureTask(task1);
-
MyCallable task2 = new MyCallable(1);
-
FutureTask ft2 = new FutureTask(task2);
-
MyCallable task3 = new MyCallable(2);
-
FutureTask ft3 = new FutureTask(task3);
-
-
try {
-
//启动task1
-
new Thread(ft1, "子线程").start();
-
System.out.println(ft1.get());
-
-
-
//等待5秒后,停止task2
-
new Thread(ft2, "子线程").start();
-
Thread.sleep(5000);
-
System.out.println("task2 cancel:" + ft2.cancel(true));
-
-
//启动task3
-
new Thread(ft3, "子线程").start();
-
System.out.println("task3:" + ft3.get());
-
} catch (InterruptedException | ExecutionException e) {
-
-
System.out.println(e.toString());
-
}
-
-
}
其执行结果与方法一完全相同,对比这两种方式,第二种比较容易读懂,第一种相对困难些。下篇博客我们介绍Executor、ExecutorService等内容,相信之后理解起来就会很轻松了。
java线程——详解Callable、Future和FutureTask的更多相关文章
- Java线程池(Callable+Future模式)
转: Java线程池(Callable+Future模式) Java线程池(Callable+Future模式) Java通过Executors提供四种线程池 1)newCachedThreadPoo ...
- java线程详解
Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...
- Java线程详解----借鉴
Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...
- Java线程池 / Executor / Callable / Future
为什么需要线程池? 每次都要new一个thread,开销大,性能差:不能统一管理:功能少(没有定时执行.中断等). 使用线程池的好处是,可重用,可管理. Executor 4种线程 ...
- 【转】Java线程详解
Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...
- java线程详解(三)
java线程间通信 首先看一段代码 class Res { String name; String sex; } class Input implements Runnable { private R ...
- 并发编程 || Java线程详解
通用线程模型 在很多研发当中,实际应用是基于一个理论再进行优化的.所以,在了解JVM规范中的Java线程的生命周期之前,我们可以先了解通用的线程生命周期,这有助于我们后续对JVM线程生命周期的理解. ...
- java线程详解(二)
1,线程安全 先看上一节程序,我们稍微改动一下: //线程安全演示 //火车站有16张票,需要从四个窗口卖出,如果按照上面的多线程实现,程序如下 class Ticket implements Run ...
- java线程详解(一)
1,相关概念简介 (1)进程:是一个正在执行的程序.每一个进程执行都有一个执行的顺序,该顺序就是一个执行路径,或者叫一个控制单元.用于分配空间. (2)线程:就是进程中一个独立的控制单元,线程在控制着 ...
随机推荐
- selenium与phantomjs简单结合
selenium工具安装 Windows安装pip install selenium Linux安装apt-get install selenium 查看selenium支持的浏览器from sele ...
- 进阶《Python高性能编程》中文PDF+英文PDF+源代码
入门使用高性能 Python,建议参考<Python高性能编程>,例子给的很多,讲到高性能就会提到性能监控,里面有cpu mem 方法的度量,网络讲了一点异步,net profiler 没 ...
- 【Docker构建私有仓库】
Docker默认不允许非HTTPS方式推送镜像,我们可以通过Docker的配置选项来取消此限制: [root@fedora ~]# cat /etc/docker/daemon.json { &quo ...
- 51nod 正整数分组
将一堆正整数分为2组,要求2组的和相差最小. 显然我们可以把所有可能组合成的数求出来. 然后从总和的中间开始往大找,找到了就是其中一个的分组,就可以求出答案了. #include<cstdio& ...
- Jsp学习总结(1)——JSP九大内置对象和四种属性范围解读
一.四种属性范围 1.1.在JSP中提供了四种属性保存范围 page:在一个页面内保存属性,跳转之后无效 request:在一次服务请求范围内,服务器跳转后依然有效 session:-在一次会话范围内 ...
- 洛谷 P1994 有机物燃烧
P1994 有机物燃烧 题目背景 本来准备弄难点的,还是算了吧 题目描述 输入一种有机物,输出与氧气反应化学方程式中CO2和H2O的系数 输入输出格式 输入格式: 一行,一个字符串,表示有机物 输出格 ...
- 洛谷 P1877 [HAOI2012]音量调节
P1877 [HAOI2012]音量调节 题目描述 一个吉他手准备参加一场演出.他不喜欢在演出时始终使用同一个音量,所以他决定每一首歌之前他都需要改变一次音量.在演出开始之前,他已经做好一个列表,里面 ...
- STL heap部分源代码分析
本文假设你已对堆排序的算法有主要的了解. 要分析stl中heap的源代码的独到之处.最好的办法就是拿普通的代码进行比較.话不多说,先看一段普通的堆排序的代码: //调整大顶堆.使得结构合理 void ...
- js函数的属性和方法
js函数的属性和方法 前面的话 函数是javascript中特殊的对象,可以拥有属性和方法,就像普通的对象拥有属性和方法一样.甚至可以用Function()构造函数来创建新的函数对象.本文是深入理解j ...
- 47.Express文件上传
转自:http://www.runoob.com/nodejs/nodejs-express-framework.html 文件上传 以下我们创建一个用于上传文件的表单,使用 POST 方法,表单 e ...