欢迎光临
我们一直在努力

Java中Future类如何实现异步任务执行与结果获取?

JAVA Future类的使用详解

Java中Future类如何实现异步任务执行与结果获取?

在并发编程中,Future接口提供了一种用于表示异步计算结果的机制,通过Future,我们可以启动异步任务,并在稍后获取其执行结果,本文将详细介绍Java中Future类的使用方法、应用场景及其与其他相关类的关系。

一、Future的应用场景

Future常用于以下场景:

异步任务:启动一个长时间运行的任务,并允许主线程继续执行其他操作,而不必等待任务完成。

并行处理:同时启动多个任务,并在所有任务完成后再进行下一步操作。

非阻塞模型:避免因等待某个耗时操作而阻塞整个程序的执行。

在准备早餐时,如果包子需要3分钟,凉菜只需1分钟,采用串行方式需要4分钟才能吃完早餐,但如果采用Future模式,可以同时准备包子和凉菜,从而缩短总时间。

二、Future的类图结构

Future接口定义了五个主要的方法:

V get() throws InterruptedException, ExecutionException: 当任务结束后返回结果;如果任务未完成,则阻塞直到任务完成。

V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException: 等待指定时间后返回结果;如果超时则抛出异常。

boolean cancel(boolean mayInterruptIfRunning): 取消任务;如果任务正在运行且mayInterruptIfRunning为true,则尝试中断任务。

boolean isDone(): 判断任务是否已完成。

Java中Future类如何实现异步任务执行与结果获取?

boolean isCancelled(): 判断任务是否已取消。

实现类

RunnableFuture: 同时继承Future和Runnable接口,在成功执行run方法后,可以通过Future访问执行结果,典型实现类是FutureTask。

SchedualFuture: 表示一个延时的行为可以被取消,通常由定时任务ScheduledExecutorService生成。

CompleteFuture: 显示完成的Future,用作完成等级,触发依赖函数和行为。

ForkJoinTask: 基于任务的抽象类,通过ForkJoinPool执行轻量级任务。

三、Future的主要方法

1、get()方法: 获取任务的结果,如果任务尚未完成,则会阻塞当前线程直到任务完成。

   Future<Integer> future = executor.submit(callableTask);
   Integer result = future.get(); // 如果任务未完成,则阻塞直到完成

2、get(long timeout, TimeUnit unit)方法: 在指定时间内等待任务完成,如果超时则抛出异常。

   Integer result = future.get(5, TimeUnit.SECONDS); // 等待最多5秒

3、cancel(boolean mayInterruptIfRunning)方法: 取消任务。

   boolean cancelled = future.cancel(true); // true表示如果任务正在运行则尝试中断它

4、isDone()方法: 检查任务是否已完成。

   boolean done = future.isDone();

5、isCancelled()方法: 检查任务是否已被取消。

Java中Future类如何实现异步任务执行与结果获取?

   boolean cancelled = future.isCancelled();

四、Future示例demo

需求场景:等早餐过程中,包子需要3秒,凉菜需要1秒,普通的多线程需要四秒才能完成,先等凉菜,再等包子,采用Future模式可以优化这个过程。

普通多线程实现

public class BumThread extends Thread {
    @Override
    public void run() {
        try {
            Thread.sleep(3000);
            System.out.println("包子准备完毕");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class ColdDishThread extends Thread {
    @Override
    public void run() {
        try {
            Thread.sleep(1000);
            System.out.println("凉菜准备完毕");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public static void main(String[] args) throws InterruptedException {
    long start = System.currentTimeMillis();
    Thread t1 = new ColdDishThread();
    t1.start();
    t1.join();
    Thread t2 = new BumThread();
    t2.start();
    t2.join();
    long end = System.currentTimeMillis();
    System.out.println("准备完毕时间:" + (end  start));
}

Future模式实现

public static void main(String[] args) throws InterruptedException, ExecutionException {
    long start = System.currentTimeMillis();
    Callable<String> ca1 = () > {
        Thread.sleep(1000);
        return "凉菜准备完毕";
    };
    FutureTask<String> ft1 = new FutureTask<>(ca1);
    new Thread(ft1).start();
    System.out.println(ft1.get()); // 获取凉菜结果

    Callable<String> ca2 = () > {
        Thread.sleep(3000);
        return "包子准备完毕";
    };
    FutureTask<String> ft2 = new FutureTask<>(ca2);
    new Thread(ft2).start();
    System.out.println(ft2.get()); // 获取包子结果

    long end = System.currentTimeMillis();
    System.out.println("准备完毕时间:" + (end  start));
}

在这个示例中,通过使用FutureTask,我们可以在等待凉菜的同时启动包子的准备过程,从而减少了总的等待时间。

五、相关问题与解答栏目

1、问题1:Future和Callable有什么区别?

回答:Future是一个接口,用于表示异步计算的结果;而Callable是一个泛型接口,类似于Runnable,但它可以返回一个结果并能抛出异常,Callable通常与Future一起使用,通过ExecutorService提交Callable任务后会返回一个Future对象,用于获取任务的结果。

2、问题2:如何取消一个已经提交的Future任务?

回答:可以使用Future接口中的cancel方法来取消任务,如果任务已经完成或已经被取消,则cancel方法返回false;否则根据mayInterruptIfRunning参数决定是否中断正在运行的任务,如果mayInterruptIfRunning为true且任务正在运行,则会尝试中断它。

到此,以上就是小编对于“JAVA Future类的使用详解”的问题就介绍到这了,希望介绍的几点解答对大家有用,有任何问题和不懂的,欢迎各位朋友在评论区讨论,给我留言。

赞(0)
版权声明:本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
文章名称:《Java中Future类如何实现异步任务执行与结果获取?》
文章链接:https://yuyunkj.com/article/10703.html
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。

评论 抢沙发