多线程中Future与FutureTask的区别

线程可以通过实现Runnable接口,或者继承Thread实现,但是这两种方式在任务执行完成之后无法获取返回结果,于是就有了Callable接口,Future接口与FutureTask类配和来取得返回的结果。

Runnable

从Runable的方法可以看到,是一个没有返回值的线程。
在这里插入图片描述

Callable

Callable与Runnable的功能大致相似,Callable中有一个call()函数,但是call()函数有返回值,而Runnable的run()函数不能将结果返回给客户程序。Callable的声明如下 :
在这里插入图片描述

Future

Future用来获取异步计算结果,提供以下方法声明

 boolean cancel(boolean mayInterruptIfRunning);
 boolean isCancelled();
 boolean isDone();
 V get() throws InterruptedException, ExecutionException
 V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;

  • V get() :获取异步执行的结果,如果没有结果可用,此方法会阻塞直到异步计算完成。
    boolean isDone() :任务结束返回true;
  • V get(Long timeout , TimeUnit unit) :获取异步执行结果,如果没有结果可用,此方法会阻塞,但是会有时间限制,如果阻塞时间超过设定的timeout时间,该方法将抛出异常。
  • boolean isCancelled() :如果任务完成前被取消,则返回true。
  • boolean cancel(boolean mayInterruptRunning) :用来取消任务,如果任务还没开始,或者任务已经完成,执行cancel(…)方法将返回false;如果任务已经启动,执行cancel(true)方法将以中断执行此任务线程的方式来试图停止任务,如果停止成功,返回true;当任务已经启动,执行cancel(false)方法将不会对正在执行的任务线程产生影响(让线程正常执行到完成),此时返回false;mayInterruptRunning参数表示是否中断执行中的线程。
FutureTask
public class FutureTask<V> implements RunnableFuture<V>
public interface RunnableFuture<V> extends Runnable, Future<V>

FutureTask类实现了RunnableFuture接口,FutureTask除了实现了Future接口外还实现了Runnable接口。FutureTask类是Future唯一实现类。
使用FutureTask时,根据FutureTask的构造函数可以看到FutureTask既可以接收Callable的实现类,也可以接收Runnable的实现类。当你传入的是Callable的实现类时,可以获取线程执行的结果;传入Runnable的实现类时,由于Runnable的实现没有返回值,需要传入一个你设置的线程完成标识,也就是result,然后当线程结束时会把你传入的result原值返回。

Callable/Future/FutureTask的使用 (封装了异步获取结果的Future!!!)

Callable实现类如下:

package com.zejian.Executor;  
import java.util.concurrent.Callable;  
/** 
 * @author zejian 
 * @time 2016年3月15日 下午2:02:42 
 * @decrition Callable接口实例 
 */  
public class CallableDemo implements Callable<Integer> {  
      
    private int sum;  
    @Override  
    public Integer call() throws Exception {  
        System.out.println("Callable子线程开始计算啦!");  
        Thread.sleep(2000);  
          
        for(int i=0 ;i<5000;i++){  
            sum=sum+i;  
        }  
        System.out.println("Callable子线程计算结束!");  
        return sum;  
    }  
} 

Callable执行测试类如下:

    package com.zejian.Executor;  
    import java.util.concurrent.ExecutorService;  
    import java.util.concurrent.Executors;  
    import java.util.concurrent.Future;  
    /** 
     * @author zejian 
     * @time 2016年3月15日 下午2:05:43 
     * @decrition callable执行测试类 
     */  
    public class CallableTest {  
          
        public static void main(String[] args) {  
            //创建线程池  
            ExecutorService es = Executors.newSingleThreadExecutor();  
            //创建Callable对象任务  
            CallableDemo calTask=new CallableDemo();  
            //提交任务并获取执行结果  
            Future<Integer> future =es.submit(calTask);  
            //关闭线程池  
            es.shutdown();  
            try {  
                Thread.sleep(2000);  
            System.out.println("主线程在执行其他任务");  
              
            if(future.get()!=null){  
                //输出获取到的结果  
                System.out.println("future.get()-->"+future.get());  
            }else{  
                //输出获取到的结果  
                System.out.println("future.get()未获取到结果");  
            }  
              
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
            System.out.println("主线程在执行完成");  
        }  
    }  

执行结果

Callable子线程开始计算啦!
主线程在执行其他任务
Callable子线程计算结束!
future.get()-->12497500
主线程在执行完成
使用Callable+FutureTask获取执行结果
    package com.zejian.Executor;  
    import java.util.concurrent.ExecutorService;  
    import java.util.concurrent.Executors;  
    import java.util.concurrent.Future;  
    import java.util.concurrent.FutureTask;  
    /** 
     * @author zejian 
     * @time 2016年3月15日 下午2:05:43 
     * @decrition callable执行测试类 
     */  
    public class CallableTest {  
          
        public static void main(String[] args) {  
    //      //创建线程池  
    //      ExecutorService es = Executors.newSingleThreadExecutor();  
    //      //创建Callable对象任务  
    //      CallableDemo calTask=new CallableDemo();  
    //      //提交任务并获取执行结果  
    //      Future<Integer> future =es.submit(calTask);  
    //      //关闭线程池  
    //      es.shutdown();  
              
            //创建线程池  
            ExecutorService es = Executors.newSingleThreadExecutor();  
            //创建Callable对象任务  
            CallableDemo calTask=new CallableDemo();  
            //创建FutureTask  
            FutureTask<Integer> futureTask=new FutureTask<>(calTask);  
            //执行任务  
            es.submit(futureTask);  
            //关闭线程池  
            es.shutdown();  
            try {  
                Thread.sleep(2000);  
            System.out.println("主线程在执行其他任务");  
              
            if(futureTask.get()!=null){  
                //输出获取到的结果  
                System.out.println("futureTask.get()-->"+futureTask.get());  
            }else{  
                //输出获取到的结果  
                System.out.println("futureTask.get()未获取到结果");  
            }  
              
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
            System.out.println("主线程在执行完成");  
        }  
    } 

执行结果

Callable子线程开始计算啦!
主线程在执行其他任务
Callable子线程计算结束!
futureTask.get()-->12497500
主线程在执行完成
Future与FutureTask分析

我们从ExecutorService接口中submit方法入手,看下AbstractExecutorService类对submit方法的具体实现。

在这里插入图片描述
使用submit方法提交任务时,都会通过newTaskFor方法转换成FutureTask对象。
所以ExecutorService接口中submit方法归根结底还是要把你传入的对象封装成FutureTask对象,并通过FutureTask类的内部实现来获取结果的,返回的Future接口对象也要依赖于FutureTask实例化的,所以无论是直接传入自己的Runnable、Callable实现类还是构建FutureTask传入,本质上都是通过FutureTask去实现,没有什么区别

参考
https://blog.csdn.net/sx1119183530/article/details/79735348
https://juejin.cn/post/6844903811950051342

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值