JAVA-Runnable、Callable、FutureTask
通常,创建线程的执行单元有两种,一种是直接继承 Thread,另外一种就是实现 Runnable 接口。
但这两种都有一个问题就是无法有返回值,且子线程在执行过程中无法抛出异常。想线程有返回值,可以使用 Callable 来创建执行单元。
Runnable
一个接口,没有返回值
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
Callable
一个接口,有返回值,且允许抛出异常
@FunctionalInterface
public interface Callable<V> {
V call() throws Exception;
}
FutureTask
Future 接口的实现类,用于包装 Runnable 或 Callable,用于获得线程的执行结果,且允许中断线程执行过程,还可用于判断线程是否执行完成
/**
* boolean isCancelled()
* 任务是否被取消成功,如果在任务正常完成前被取消成功,则返回 true。
*
* V get()
* 获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回
*
* V get(long timeout, TimeUnit unit)
* 在指定时间内尝试获取执行结果。若超时则抛出超时异常
*
* Boolean isDone()
* 任务是否已经完成(包括正常执行完毕、执行异常或者任务取消),若任务完成,则返回 true
*
* boolean cancel(boolean mayInterruptInRunning)
* 取消任务,如果取消任务成功则返回 true,如果取消任务失败则返回 false
* 参数 mayInterruptIfRunning 表示是否允许取消正在执行却没有执行完毕的任务,如果设置 true,则表示可以取消正在执行过程中的任务
* 如果任务已经完成,则无论 mayInterruptIfRunning 为 true 还是 false,此方法肯定返回 false,即如果取消已经完成的任务会返回 false
* 如果任务正在执行,若 mayInterruptIfRunning 设置为 true,则返回 true,若 mayInterruptIfRunning 设置为 false,则返回 false
* 如果任务还没有执行,则无论 mayInterruptIfRunning 为 true 还是 false,肯定返回 true
*/

线程池中的 (java.util.concurrent.AbstractExecutorService)submit 方法,将任务包装成 RunnableFuture 再执行
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
public <T> Future<T> submit(Runnable task, T result) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task, result);
execute(ftask);
return ftask;
}
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
使用示例
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
};
// 无返回值
FutureTask<?> rFutureTask = new FutureTask<Void>(runnable, null);
// 返回指定值
// FutureTask<String> rFutureTask = new FutureTask<String>(runnable, "OK");
System.out.println(rFutureTask.isDone());
new Thread(rFutureTask).start();
Callable<String> callable = new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(1000);
return Thread.currentThread().getName();
}
};
FutureTask<String> cFutureTask = new FutureTask(callable);
new Thread(cFutureTask).start();
System.out.println(cFutureTask.isCancelled());
// 获取结果
System.out.println(cFutureTask.get());
https://www.cnblogs.com/dolphin0520/p/3949310.html
https://www.cnblogs.com/maypattis/p/5827671.html
JAVA-Runnable、Callable、FutureTask的更多相关文章
- Java中的Runnable、Callable、Future、FutureTask的区别与示例
Java中存在Runnable.Callable.Future.FutureTask这几个与线程相关的类或者接口,在Java中也是比较重要的几个概念,我们通过下面的简单示例来了解一下它们的作用于区别. ...
- java Runnable、Callable、FutureTask 和线程池
一:Runnable.Callable.FutureTask简介 (1)Runnable:其中的run()方法没有返回值. ①.Runnable对象可以直接扔给Thread创建线程实例,并且创建的线程 ...
- Runnable、Callable、Executor、Future、FutureTask关系解读
在再度温习Java5的并发编程的知识点时发现,首要的就是把Runnable.Callable.Executor.Future等的关系搞明白,遂有了下述小测试程序,通过这个例子上述三者的关系就一目了然了 ...
- Runnable、Callable、Future和FutureTask之二:源码解析
一.Callable与Future类图 1.类图 许多任务实际上都是存在延迟的计算,对于这些任务,Callable是一种更好的抽象:它会返回一个值,并可能抛出一个异常.Callable接口: V ca ...
- Android进阶——多线程系列之Thread、Runnable、Callable、Future、FutureTask
多线程一直是初学者最抵触的东西,如果你想进阶的话,那必须闯过这道难关,特别是多线程中Thread.Runnable.Callable.Future.FutureTask这几个类往往是初学者容易搞混的. ...
- Java并发(8):CountDownLatch、CyclicBarrier、Semaphore、Callable、Future
CountDownLatch.CyclicBarrier.Semaphore.Callable.Future 都位于java.util.concurrent包下,其中CountDownLatch.C ...
- Java 并发编程——Callable+Future+FutureTask
Java 并发编程系列文章 Java 并发基础——线程安全性 Java 并发编程——Callable+Future+FutureTask java 并发编程——Thread 源码重新学习 java并发 ...
- ExecutorService、Callable、Future实现有返回结果的多线程原理解析
原创/朱季谦 在并发多线程场景下,存在需要获取各线程的异步执行结果,这时,就可以通过ExecutorService线程池结合Callable.Future来实现. 我们先来写一个简单的例子-- pub ...
- Java中的Runnable、Callable、Future、FutureTask的区别
本文转载自:http://blog.csdn.net/bboyfeiyu/article/details/24851847 Runnable 其中Runnable应该是我们最熟悉的接口,它只有一个ru ...
- Java并发:Callable、Future和FutureTask
Java并发编程:Callable.Future和FutureTask 在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一 ...
随机推荐
- Eclipse安装Hadoop插件配置Hadoop开发环境
一.编译Hadoop插件 首先需要编译Hadoop 插件:hadoop-eclipse-plugin-2.6.0.jar,然后才可以安装使用. 第三方的编译教程:https://github.com/ ...
- (转)Ubuntu换源方法
I. 查看系统版本及内核 首先查看自己的ubuntu系统的codename,这一步很重要,直接导致你更新的源是否对你的系统起效果,查看方法: lsb_release -a 如,我的系统显示: No L ...
- Java的clone方法
现在有User类:(Getter和Setter省略) public class User implements Cloneable { private String name; private int ...
- rabbitmq一键部署脚本
1.新建一个名字叫 auto_install_rabbitmq.sh 的文件 2.将下面脚本拷贝到文件中,具体操作步骤在注释里面 #环境 linux #一键安装rabitmq,在linux环境中使用 ...
- MySQL面试题(二)
● 请你说一说mysql的四种隔离状态 参考回答: Mysql主要包含四种隔离状态: 事务隔离级别 脏读 不可重复读 幻读 读未提交(read-uncommitted) 是 是 是 不可重复读(rea ...
- shell判断文件,目录是否存在或者具有权限
shell判断文件,目录是否存在或者具有权限 #!/bin/sh myPath="/var/log/httpd/" myFile="/var /log/httpd/ ...
- npm install 报错,提示`gyp ERR! stack Error: EACCES: permission denied` 解决方法
m install 报错,提示gyp ERR! stack Error: EACCES: permission denied 猜测可能是因为没有权限读写,ls -la看下文件权限设置情况 [root@ ...
- Stopwatch简单时间检测
public ActionResult Index() { Stopwatch sw = new Stopwatch(); //实例化一个对象 sw.Start(); //开始计算 int[] a = ...
- 基于树莓派2代的DIY无线路由器
最近手上多了一个树莓派2代,于是折腾就这么开始了. 因为总是得要个显示屏或者路由器或者插根网线才能玩,有点麻烦,所以有了此文. 设备清单: 树莓派2代 EDUP EP-N8508GS无线网卡(USB) ...
- mybatis解析和基本运行原理
Mybatis的运行过程分为两大步: 第1步,读取配置文件缓存到Configuration对象,用于创建SqlSessionFactory: 第2步,SqlSession的执行过程.相对而言,SqlS ...