JAVA多线程之——Future与Callable
来源:互联网 发布:sql server 2012 密钥 编辑:程序博客网 时间:2024/04/28 18:21
Futrue与Callable
在学习了多线程之后,可以知道线程的实现方式是通过继承Thread或者实现Runnable接口,当线程被启动后,会执行run方法。都知道run方法是一个void方法,也就是说线程执行完毕之后,不会返回任何东西。那么,如果我们想得到线程执行的结果怎么呢?这就要用到JUC中的Futrue与Callable了。
Callable
public interface Callable<V> { V call() throws Exception;}
Callable方法只有一个call方法,该方法返回一个泛型V对象。对比Runnable接口,该接口只有run方法,无返回值。
在调用run方法的时候,我们通常通过new一个Thread方法,传入一个Runnable接口。同理,Callable一般情况下是配合ExecutorService来使用的,在ExecutorService接口中声明了若干个submit方法的重载版本:
<T> Future<T> submit(Callable<T> task);<T> Future<T> submit(Runnable task, T result);Future<?> submit(Runnable task);
常用的是第一个和第三个。先来看一下第一个:
public <T> Future<T> submit(Callable<T> task) { if (task == null) throw new NullPointerException(); RunnableFuture<T> ftask = newTaskFor(task);//把Callable对象封装成RunnableFuture对象。 execute(ftask);//执行execute方法 return ftask;//返回一个Future对象。 }
在AbstractExecutorService里面的实现如上。在学习线程池的时候,学习过execute方法的基本执行过程,也知道它的参数是一个Runnable类型的command。因此 RunnableFuture肯定是Runnable的一个子类。 返回的是一个Future对象,那么它应该也是Future的子类。这名字取的也是够直白。把Callable对象封装成RunnableFuture调用的是 newTaskFor
newTaskFor
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) { return new FutureTask<T>(callable); }
调用构造方法
RunnableFuture
public interface RunnableFuture<V> extends Runnable, Future<V> { void run();}
注意:这里多继承是因为是接口的多继承。JAVA中只有类是单继承。别误会
Future
//取消任务,任务我们都知道有三种基本情况,已经执行完毕,正在执行,还未执行。//1.如果任务已经执行完毕,那么不管mayInterruptIfRunning是什么返回false//2.任务未执行,不管mayInterruptIfRunning方法都返回true//3.任务正在执行,那么返回的就是mayInterruptIfRunningboolean cancel(boolean mayInterruptIfRunning);//判断任务是否被取消,如果在任务正常完成前被取消成功,则返回 true。boolean isCancelled();//任务是否完成,已经完成返回trueboolean isDone();//获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回;V get() throws InterruptedException, ExecutionException;获取执行结果,如果在指定时间内,还没获取到结果,就直接返回null。V get(long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException;
再来看看RunnableFuture接口的实现类:
FutureTask
/** * Possible state transitions:状态的四种变化 * NEW -> COMPLETING -> NORMAL 正常完成 * NEW -> COMPLETING -> EXCEPTIONAL 出现了异常 * NEW -> CANCELLED 被取消 * NEW -> INTERRUPTING -> INTERRUPTED 被中断 */ private volatile int state; private static final int NEW = 0;//新建 private static final int COMPLETING = 1;//完成 private static final int NORMAL = 2;//正常 private static final int EXCEPTIONAL = 3;//异常 private static final int CANCELLED = 4;//被取消 private static final int INTERRUPTING = 5;//中断中 private static final int INTERRUPTED = 6;//被中断
构造方法
public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable }
FutureTask实现了RunnableFuture,RunnableFuture继承了Runnable接口,所以FutureTask实现run方法
run方法
public void run() { /** *首先判断任务的状态 如果任务的状态不是new 说明任务的状态已经改变(说明他已经走了4种可能变化的一种) * 如果状态是new就会把 当前执行任务的线程付给runner, 这里用的cmpandset如果runner不为空 说明已经有线程在执行 * 任务也会退出执行,如果状态是new并且runner为空并且把当前的线程付给了runner那么就继续执行任务(runner state 都是 volatile *类型的变量是一个很轻量机的线程安全操作) *引起state状态变化的原因 就是调用了cancel 或是 run if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread())) return; try { Callable<V> c = callable; if (c != null && state == NEW) { //如果是新建状态,并且c不等于空就开始执行任务 V result; boolean ran; try { result = c.call(); //调用callable对象的call方法 ran = true; } catch (Throwable ex) { result = null; ran = false; setException(ex); } if (ran) set(result); //如果正常执行完毕,设置结果 } } finally { runner = null; int s = state; if (s >= INTERRUPTING) handlePossibleCancellationInterrupt(s); }}
总结
在多线程环境中,通过任务实现Callable接口,然后调用线程池的submit方法,submit方法分两步
- 把Callable对象封装成一个FutureTask对象。(实际就是在FutureTask中有一个Callable类型的属性。)FutureTask类是RunnableFuture的实现类,RunnableFuture继承了Runnable和Future接口。在FutureTask实现了Runnable方法的run方法。run方法中对调用callable方法的call方法,然后把结果设置给FutureTask的另外一个属性。
- 调用线程池的execute方法,等待执行FutrueTask中的run方法。
当然这里只是总结一个正确的运行结果。其中可能任务会被取消,线程发生中断,异常等等情况。可以参照源码学习。其它的情况都只是一个上面状态的一个变化过程而已。
- JAVA多线程之——Future与Callable
- Java多线程——Callable与Future
- Java的多线程之Callable与Future
- java多线程之路之Callable与Future—Core Java学习
- Java多线程--Future与Callable
- JAVA---多线程之Callable与Future,FutureTask,及其简单应用
- Java多线程之 Callable、Future和FutureTask
- Java多线程之Callable和Future
- Java多线程之Callable、Future和FutureTask
- java多线程之Callable和Future
- (十八)java多线程之Callable Future
- java多线程之Callable和Future
- Java多线程之Callable、Future和FutureTask
- 黑马程序员——Java多线程—Callable、Future
- java多线程总结笔记3——Callable和Future
- Java多线程——Callable、Future和FutureTask
- Java多线程(二)——Callable、Future和FutureTask
- JAVA多线程—Callable和Future的使用介绍
- 突发事件检测: kleinberg 状态机模型
- SQL中EXISTS的用法
- bootstrap模板为使IE6、7、8版本(IE9以下版本)浏览器兼容html5和css3
- jsonp跨域同步问题解决思路
- LeetCode Week7: Jump Game&Jump GameII、Patching Arrays
- JAVA多线程之——Future与Callable
- 学习内容????????
- ListView中加入RadioButton 当点击ListView的item时,选中里面的RadioButton
- redis配置远程连接
- C语言实现扫雷
- 未来一年的计划
- Maximum Subarray
- log4j2 与 spring mvc整合
- MySQL存储引擎中的MyISAM和InnoDB