Java多线程中Callable、Future和FutureTask是什么意思

技术Java多线程中Callable、Future和FutureTask是什么意思小编给大家分享一下Java多线程中Callable、Future和FutureTask是什么意思,相信大部分人都还不怎么了解,因此分享这篇

边肖想和大家分享一下Java多线程中Callable、Future和FutureTask的含义。相信大部分人还是不太了解。因此,我想分享这篇文章供你参考。希望你看完这篇文章后收获多多。让我们一起来看看。

前言:

创建Threads有两种方法,一种是直接继承thread,另一种是实现Runnable接口。

这两种方法都有一个缺陷:在执行完任务后无法得到执行结果。

如果需要得到执行结果,必须共享变量或者使用线程通信来实现结果,使用起来比较麻烦。

从Java 1.5开始,就提供了Callable和Future,通过它们可以在任务执行后获得任务执行结果。

1 Callable介绍

Callable接口代表一段可以调用并返回结果的代码;Future接口表示异步任务,是未完成任务给出的未来结果。因此,Callable用于产生结果,Future用于获得结果。

可调用接口使用泛型来定义其返回类型。Executors类提供了一些有用的方法来执行线程池中可调用的任务。由于Callable任务是并行的(并行意味着整体看起来是并行的,但是在某个时间点只有一个线程在执行),所以我们必须等待它返回的结果。java.util.concurrent.Future对象为我们解决了这个问题。线程池提交可调用任务后,返回一个Future对象,可以用来了解可调用任务的状态,得到可调用返回的执行结果。Future提供了一个get()方法,这样我们就可以等待Callable完成并获得它的执行结果。

2 Future介绍

2.1 在Future接口中声明方法

在Future接口中声明5种方法下面依次解释每个方法的作用:

Java多线程中Callable、Future和FutureTask是什么意思

00-1010 1)判断任务是否完成;

2)中断任务的能力;

3)得到任务执行的结果。

因为Future只是一个接口,不能直接用来创建对象,所以有下面的FutureTask。

2.2 Future提供了三种功能

我们先来看一下FutureTask的实现:

公共类FutureTaskV实现RunnableFutureV

FutureTask类实现了RunnableFuture接口,我们看一下RunnableFuture接口的实现:

public interface cerunnablefurtevextendrunnable,FutureV {

虚空运行();

}可以看出RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。因此,它可以作为Runnable由线程执行,也可以作为Future来获取Callable的返回值。

FutureTask提供了2个构造器:

public futuretask(CallableVcallable){ 0

}

public futuretask(runnable runnable,Vnbsp

;result) {
}

事实上,FutureTaskFuture接口的一个唯一实现类。

4 Future和FutureTask的使用

4.1 使用Callable+Future获取执行结果

public class CallableFutureTest {
    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("主线程在执行完成");
    }
}
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 < 100; i++) {
            sum = sum + i;
        }
        System.out.println("Callable子线程计算结束!");
        return sum;
    }
}

Callable子线程开始计算啦!
Callable子线程计算结束!
主线程在执行其他任务
future.get()-->4950
主线程在执行完成

4.2 使用Callable+Future获取执行结果

public class CallableFutureTest {
    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("主线程在执行完成");
    }
}
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 < 100; i++) {
            sum = sum + i;
        }
        System.out.println("Callable子线程计算结束!");
        return sum;
    }
}

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

但其实这两种方法最终是一样的:
第一种方式Callable+Future最终也是以Callable+FutureTask的形式实现的。
在第一种方式中调用了: Future future = executor.submit(task);
那就让我们看看executor.submit(task)的源码吧:

//java.util.concurrent.AbstractExecutorService类中
   /**
     * @throws RejectedExecutionException {@inheritDoc}
     * @throws NullPointerException       {@inheritDoc}
     */
    public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);//可以看到源码中其实是在submit(Callable<T> task)内部创建了一个RunnableFuture<T>接口实现类
        execute(ftask);
        return ftask;
    }

FutureTask又是RunnableFuture的实现类,那就再看看newTaskFor(Callable callable)里面干了什么:

 protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }

以上是“Java多线程中Callable、Future和FutureTask是什么意思”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/60759.html

(0)

相关推荐

  • 如何用VB.NET创建三层结构的应用程序

    技术如何用VB.NET创建三层结构的应用程序这篇文章主要为大家展示了“如何用VB.NET创建三层结构的应用程序”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何用VB.NET

    攻略 2021年12月1日
  • Linux系统中怎么使用TFTP

    技术Linux系统中怎么使用TFTP这篇文章主要讲解了“Linux系统中怎么使用TFTP”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Linux系统中怎么使用TFTP”吧

    攻略 2021年11月30日
  • 英文大小写26个字母,二十六个字母大小写及音标是

    技术英文大小写26个字母,二十六个字母大小写及音标是一英文大小写26个字母、26个英文字母的大写字母 A、B、C、D、E、F、G、H、I、J、K、L、M、N、O、P、Q、R、S、T、U、V、W、X、Y、Z。
    二、26个

    生活 2021年10月24日
  • jq笔记汇总

    技术jq笔记汇总 jq笔记汇总alert(); 这是简写
    window.alert(); 这是全称,所以可以直接来一个 onload= function (){}jquery对象的三种表现形式
    $(do

    礼包 2021年11月9日
  • 80创业,80年代后应该如何创业

    技术80创业,80年代后应该如何创业如今的80后有着自己独特的创业方式80创业,但无论何种方式都不能脱离脚踏实地。创业对于80后来说是一次人生的转折,是一次新的选择,所以要谨慎,更要去坚持。
    第一条,确定方向
    方向不是目

    生活 2021年10月27日
  • Hibernate HQL优化的方法有哪些

    技术Hibernate HQL优化的方法有哪些这篇文章主要讲解了“Hibernate HQL优化的方法有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Hibernat

    攻略 2021年12月4日