0

0

java中Future与FutureTask之间的关系及使用(附代码)

不言

不言

发布时间:2018-10-15 15:46:46

|

2742人浏览过

|

来源于博客园

转载

本篇文章给大家带来的内容是关于java中future与futuretask之间的关系及使用(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

Future与FutureTask都是用于获取线程执行的返回结果。下面我们就对两者之间的关系与使用进行一个大致的介绍与分析

一、Future与FutureTask介绍

Future位于java.util.concurrent包下,它是一个接口

public interface Future {
    boolean cancel(boolean mayInterruptIfRunning);
    boolean isCancelled();
    boolean isDone();
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

立即学习Java免费学习笔记(深入)”;

Red Panda AI
Red Panda AI

AI文本生成图像

下载

Future接口中声明了5个方法,下面介绍一下每个方法的作用:

cancel方法用来取消任务,取消成功则返回true,取消失败则返回false。参数mayInterruptIfRunning设置为false,表示不允许在线程运行时中断,设置为true则表示允许。具体可分为以下三种情况:

        1、如果任务已经完成,则无论mayInterruptIfRunning为true还是false,都返回false,这是因为你要取消的任务已经完成,则认为取消任务失败;

        2、如果任务正在执行,则无论mayInterruptIfRunning为true还是false,都返回true。只不过mayInterruptIfRunning为true时线程会被中断,false时线程不会被中断会执行完。

        3、如果任务还没有执行,则无论mayInterruptIfRunning为true还是false,都返回true。

isCancelled方法用于判断任务是否被取消成功,cancel方法成功则返回 true,反之则为false。

isDone用于判断任务是否完成,  如果任务完成则返回true。任务完成包括正常结束、任务被取消、任务发生异常,都返回true

get()方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回;

get(long timeout, TimeUnit unit)用来获取执行结果,如果在指定时间内,还没获取到结果,抛出 java.util.concurrent.TimeoutException 异常 

FutureTask 实现了RunnableFuture接口,而RunnableFuture则继承了Future与Runnable接口,所以 FutureTask不仅实现了 Future接口的所有方法,还具有自己的run方法,我们可以看下它的类图

、Future与FutureTask使用与分析

1、使用Future时,我们需要实现Callable接口,并通过ExecutorService接口的submit方法获取返回的Future对象,

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

public class FutureTask implements RunnableFuture{
     public FutureTask(Callable callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
     }
     public FutureTask(Runnable runnable, V result) {
        this.callable = Executors.callable(runnable, result);//runnable转化为callable 
        this.state = NEW;       // ensure visibility of callable
     }
}

立即学习Java免费学习笔记(深入)”;

 接下来我们看下Future与FutureTask具体的使用代码:

       // 执行任务 实现Runnable
        FutureTaskJobRunnable taskRun = new FutureTaskJobRunnable();
        // 执行任务 实现Callable
        FutureTaskJobCallable taskCall = new FutureTaskJobCallable();
        String val = "ok";
        // 线程运行成功后把,返回你传入的val值
        FutureTask futureTaskRun = new FutureTask(taskRun, val);
        // 线程运行,返回线程执行的结果
        FutureTask futureTaskCall = new FutureTask(taskCall);
        //声明线程池
        ExecutorService executor = Executors.newCachedThreadPool();        
        //Future
        Future future =  executor.submit(taskCall);
        System.out.println(future.get());
        //FutureTask
        executor.submit(futureTaskCall);
        System.out.println(futureTaskCall.get());
        //FutureTask自定义线程执行
        new Thread(futureTaskRun).start();
        System.out.println(futureTaskRun.get());

立即学习Java免费学习笔记(深入)”;

public class FutureTaskJobCallable implements Callable{
    
    public String call() throws Exception {
        System.out.println("FutureTaskJobCallable已经执行了哦");
        Thread.sleep(1000);
        return "返回结果";
    }
}
public class FutureTaskJobRunnable implements Runnable {
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("FutureTaskJobRunnable已经执行了哦");
    }
}

立即学习Java免费学习笔记(深入)”;

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

public Future submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture ftask = newTaskFor(task, null);
        execute(ftask);
        return ftask;
    }
    public  Future submit(Runnable task, T result) {
        if (task == null) throw new NullPointerException();
        RunnableFuture ftask = newTaskFor(task, result);
        execute(ftask);
        return ftask;
    }
    public  Future submit(Callable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }
    protected  RunnableFuture newTaskFor(Runnable runnable, T value) {
        return new FutureTask(runnable, value);
    }
    protected  RunnableFuture newTaskFor(Callable callable) {
        return new FutureTask(callable);
    }

立即学习Java免费学习笔记(深入)”;

可以看到当你使用submit方法提交任务时,都会通过newTaskFor方法转换成FutureTask对象,所以我们具体分析下上面代码中的三种情况:

1、如果你传入的是自己实现的Runaable类或者Callable类,那么sumbit方法自然会帮你自动封装为FutureTask对象,运行后通过Future对象获取结果。

2、你传入的已经是个自己构造的FutureTask对象,由于FutureTask其实是实现了Runnable接口的,它本身就是个Runaable实现类, sumbit方法还是会将它视为Runnable类来进行封装,并最终会执行FutureTask自己的run方法,一系列实现都在你传入的FutureTask对象内完成,所以你可以直接通过自己构建的FutureTask获取结果;

3、自己单独声明线程运行,跟第2点类似,FutureTask本身就是个Runnabel实现类,自然可以做为参数传入Thread运行;

那么我们把自定义的Runnable、Callable实现类做为参数构造FutureTask后,FuttureTask是如何运行的呢,我们可以看下FuttureTask中具体的代码实现

//你传入的Runnable与Callable实现类都会在构造函数中转化为Callable
private Callable callable;
    public void run() {
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         null, Thread.currentThread()))
            return;
        try {
            Callable c = callable;//你传入的实现类
            if (c != null && state == NEW) {
                V result;//返回值
                boolean ran;
                try {
                    result = c.call();//运行后返回结果
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }

立即学习Java免费学习笔记(深入)”;

可以看到FutureTask类本身的run方法,就是执行Runnable、Callable的实现类并获取返回结果的过程。

所以ExecutorService接口中submit方法归根结底还是要把你传入的对象封装成FutureTask对象,并通过FutureTask类的内部实现来获取结果的,返回的Future接口对象也要依赖于FutureTask实例化的,所以无论是直接传入自己的Runnable、Callable实现类还是构建FutureTask传入,本质上都是通过FutureTask去实现,没有什么区别;

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

2

2025.12.31

php网站源码教程大全
php网站源码教程大全

本专题整合了php网站源码相关教程,阅读专题下面的文章了解更多详细内容。

0

2025.12.31

视频文件格式
视频文件格式

本专题整合了视频文件格式相关内容,阅读专题下面的文章了解更多详细内容。

2

2025.12.31

不受国内限制的浏览器大全
不受国内限制的浏览器大全

想找真正自由、无限制的上网体验?本合集精选2025年最开放、隐私强、访问无阻的浏览器App,涵盖Tor、Brave、Via、X浏览器、Mullvad等高自由度工具。支持自定义搜索引擎、广告拦截、隐身模式及全球网站无障碍访问,部分更具备防追踪、去谷歌化、双内核切换等高级功能。无论日常浏览、隐私保护还是突破地域限制,总有一款适合你!

6

2025.12.31

出现404解决方法大全
出现404解决方法大全

本专题整合了404错误解决方法大全,阅读专题下面的文章了解更多详细内容。

27

2025.12.31

html5怎么播放视频
html5怎么播放视频

想让网页流畅播放视频?本合集详解HTML5视频播放核心方法!涵盖<video>标签基础用法、多格式兼容(MP4/WebM/OGV)、自定义播放控件、响应式适配及常见浏览器兼容问题解决方案。无需插件,纯前端实现高清视频嵌入,助你快速打造现代化网页视频体验。

3

2025.12.31

关闭win10系统自动更新教程大全
关闭win10系统自动更新教程大全

本专题整合了关闭win10系统自动更新教程大全,阅读专题下面的文章了解更多详细内容。

2

2025.12.31

阻止电脑自动安装软件教程
阻止电脑自动安装软件教程

本专题整合了阻止电脑自动安装软件教程,阅读专题下面的文章了解更多详细教程。

1

2025.12.31

html5怎么使用
html5怎么使用

想快速上手HTML5开发?本合集为你整理最实用的HTML5使用指南!涵盖HTML5基础语法、主流框架(如Bootstrap、Vue、React)集成方法,以及无需安装、直接在线编辑运行的平台推荐(如CodePen、JSFiddle)。无论你是新手还是进阶开发者,都能轻松掌握HTML5网页制作、响应式布局与交互功能开发,零配置开启高效前端编程之旅!

2

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 2.1万人学习

C# 教程
C# 教程

共94课时 | 5.7万人学习

Java 教程
Java 教程

共578课时 | 39.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号