FutureTask——另一种闭锁的实现
关于多线程,我们接触对多的,最基础,入门的可能就是实现Runnable接口继承Thead类,因为Java单继承的原因,通常建议是实现Runnable接口。但这种“简单”的线程会带来一个问题,写过的人都知道,不管是实现Runnable还是继承Thread类,他们都是实现public void run()方法,而这个方法可以看到是没有返回值的。但我们想执行一个线程得到它的返回值应该怎么做呢?此时FutureTask就要出场了。
首先我们还是需要定义一个线程,不同的是这个线程需要实现Callable接口。这是第一个不同的地方。
package futuretask; import java.util.concurrent.Callable; /**
* Created by yulinfeng on 12/17/16.
*/
public class Task implements Callable<String> {
private String name; public Task(String name){
this.name = name;
} @Override
public String call() throws Exception {
String hello = hello(name);
return hello;
} public String hello(String name){
return "hello " + name;
}
}
可以看到此时并不是实现run方法,而是一个叫call的方法,同时有返回值(返回值取决于所定义的泛型)。定义好这个线程过后,并不是直接将此线程的实例传入一个Thread类中执行start方法,这也是和没有返回值的线程不同的地方。
下面我们通过两种方法使用FutureTask,一个是通过线程池的方式创建线程,一个是直接创建一个线程。
通过多线程的方式创建线程:
package futuretask; import countdownlatch.TaskThread; import java.util.concurrent.*; /**
* Created by yulinfeng on 12/17/16.
*/
public class Test {
public static void main(String[] args){
ExecutorService exec = Executors.newCachedThreadPool(); //创建一个线程池
Future<String> hello = exec.submit(new Task("kevin")); //执行线程池的submit方法,执行callable线程,并返回一个Future对象
try {
System.out.println(hello.get()); //通过调用Future的get方法,获取线程的返回值
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
这是第一种通过线程池创建线程的方式,通过调用线程的submit方法。如果是实现的Runnable方法,通过线程池创建线程执行的则是线程池的execute方法。一定注意调用线程返回值时使用的是Future的get方法来获取的返回值。
直接创建线程:
package futuretask; import countdownlatch.TaskThread; import java.util.concurrent.*; /**
* Created by yulinfeng on 12/17/16.
*/
public class Test {
public static void main(String[] args){
FutureTask<String> future = new FutureTask<String>(new Task("kevin")); //将线程传入FuturaTask的构造方法中
Thread thread = new Thread(future);
thread.start();
try {
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
在调用get方法时,一定是在执行完线程后,不然将会一直阻塞。
其实仔细观察以上两张方法,第一种是Future接口,第二种是FutureTask类。FutureTask是Future接口的实现,为什么不能将Future接口传入Thread的构造方法中呢?原因很简单。在Thread的单个参数构造方法中,只能传入Runnable类型,而Future并没有继承Runnable接口,FutureTask则同时继承了Runnable接口和Future接口。
最后,那么FutureTask应该怎么来定义呢?其实和我们上一节将的CountDownLatch一样,它也是一种闭锁的实现。Future.get取决于任务的状态,如果任务已完成,那么get会立即返回结果,否则get将阻塞直到任务进入完成状态,然后返回结果或者抛出异常。FutureTask将计算结果从执行计算的线程传递到获取这个结果的线程,而FutureTask的规范确保了这种传递过程能实现结果的安全发布。——《Java并发编程实践》
FutureTask——另一种闭锁的实现的更多相关文章
- 并发编程-Future+callable+FutureTask 闭锁机制
项目中经常有些任务需要异步(提交到线程池中)去执行,而主线程往往需要知道异步执行产生的结果,这时我们要怎么做呢?用runnable是无法实现的,我们需要用callable实现. FutureTask ...
- 深入浅出 Java Concurrency (10): 锁机制 part 5 闭锁 (CountDownLatch)
此小节介绍几个与锁有关的有用工具. 闭锁(Latch) 闭锁(Latch):一种同步方法,可以延迟线程的进度直到线程到达某个终点状态.通俗的讲就是,一个闭锁相当于一扇大门,在大门打开之前所有线程都被阻 ...
- 深入浅出 Java Concurrency (10): 锁机制 part 5 闭锁 (CountDownLatch)[转]
此小节介绍几个与锁有关的有用工具. 闭锁(Latch) 闭锁(Latch):一种同步方法,可以延迟线程的进度直到线程到达某个终点状态.通俗的讲就是,一个闭锁相当于一扇大门,在大门打开之前所有线程都被阻 ...
- jdk1.8 J.U.C之FutureTask实现机制分析
我画了一张关于FutureTask的类图,主要包括FutureTask的几个重要的函数和字段,还有它和父类的关系. 根据上面图我们可以清晰的看出FutureTask的继承关系.FutureTask继承 ...
- CountDownLatch——闭锁的实现之一
CountDownLatch实际上是一种闭锁实现.闭锁:是一种同步工具类,可以延迟线程的进度知道其到达终止状态--<Java并发编程实战>.这个怎么解释呢?简单来说,就是有1个线程需要等待 ...
- FutureTask理解
一.概述 FutureTask包装器是一种非常便利的机制,同时实现了Future和Runnable接口. 类图如下: FutureTask是一种可以取消的异步的计算任务.它的计算是通过Callable ...
- Callable,Future和FutureTask详解
1.Callable和Runnable 看Callable接口: public interface Callable<V> { /** * Computes a result, or th ...
- 【并发编程】【JDK源码】J.U.C--组件FutureTask、ForkJoin、BlockingQueue
原文:慕课网实战·高并发探索(十三):并发容器J.U.C -- 组件FutureTask.ForkJoin.BlockingQueue FutureTask FutureTask是J.U.C中的类,是 ...
- 并发编程—— FutureTask 源码分析
1. 前言 当我们在 Java 中使用异步编程的时候,大部分时候,我们都会使用 Future,并且使用线程池的 submit 方法提交一个 Callable 对象.然后调用 Future 的 get ...
随机推荐
- 【Egret】中tree组件使用案例
Egret中tree组件使用案例,包含(文本过多时,自动换行功能) 下面代码结合http://bbs.egret.com/forum.php?mod=viewthread&tid=19028& ...
- CSS3学习笔记(4)-CSS3函数
p{ font-size: 15px; text-indent: 2em; } .alexrootdiv>div{ background: #eeeeee; border: 1px solid ...
- JAVA加密算法系列-AES
package ***; import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; ...
- hibernate的反转引擎生成两个实体类的问题
在使用myeclipse中自带的hibernate 进行jsp开发时候遇到了这个问题.使用hibernate的反转引擎从数据库生成生成实体类,一个表生成了两个类,xx.java和xxId.java . ...
- activiti 5.15.1 动态手动通过java编码方式,实现创建用户任务,动态指定个人,用户组,角色,指定监听的实现
因为我们的业务需要,最近一直在搞动态动过java程序实现为用户任务绑定监听程序.碰了很多壁,查看了API文档,最后终于在找到解决办法,所以贴出来,希望能够留个底,也能帮助有需要的人. -------- ...
- Sublime text3 设置的中文翻译
// While you can edit this file, it's best to put your changes in // "User/Preferences.sublime- ...
- ios 获取当前设备信息、内存
//在[UIDevice currentDevice]中的属性 @property(nonatomic,readonly,strong) NSString *name; // e.g. "M ...
- MyRocks DDL原理
最近一个日常实例在做DDL过程中,直接把数据库给干趴下了,问题还是比较严重的,于是赶紧排查问题,撸了下crash堆栈和alert日志,发现是在去除唯一约束的场景下,MyRocks存在一个严重的bug, ...
- 【转载】rem自适应布局-移动端自适应必备
原文链接:rem自适应布局-移动端自适应必备 版权所有,转载时请注明出处,违者必究. 由于移动端特殊性,本文讲的是如何使用rem实现自适应,或叫rem响应式布局,通过使用一个脚本就可以rem自适应,不 ...
- AJAX做增删改查详细!
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...