Java多线程教程之如何利用Future实现携带结果的任务

目录
  • Future 介绍
  • Runnable
  • Callable
  • Future
  • 总结

Future 介绍

Future表示异步计算的结果,它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。Future的cancel方法可以取消任务的执行,它有一布尔参数,参数为 true 表示立即中断任务的执行,参数为 false 表示允许正在运行的任务运行完成。Future的 get 方法等待计算完成,获取计算结果。

Runnable

Runnable 是我们多线程开发过程中常用的接口。 Executor 框架使用 Runnable 作为其基本的任务表现形式。 Runnable 是一个有很大局限性的接口,run() 方法没有返回值并且不能抛出一个受检查的异常。

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

Callable

与 Runnable 不同,Callable 是个泛型参数化接口,它能返回线程的执行结果,出错时可能抛出异常。

多线程future

Future

Executor 执行的任务有 4 个生命周期阶段:创建、提交、开始和完成。由于有些任务执行很耗时间,因此有些时候希望能够取消这些任务。Executor 框架中,已经提交但未开始的任务可以取消,已经开始的任务只有当它们能响应中断才能取消,取消已经完成的任务是没有任何影响。

Future 表示一个任务的生命周期,并提供了相应的方法来判断任务是否已经完成或者取消,以及获取任务的结果和取消任务。

public interface Future<V> {

    // 取消任务
    boolean cancel(boolean mayInterruptIfRunning);

    // 判断是否已经取消
    boolean isCancelled();

    // 如果任务已经结束返回 true
    boolean isDone();

    // 若有必要会一直阻塞直到结束并返回结果
    V get() throws InterruptedException, ExecutionException;

    // 若有必要会阻塞指定的时间等待结束并返回结果
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

ExecutorService 中所有的 submit 方法都返回一个 Future 对象,从而将一个 Runnable 或 Callable 提交给 Executor, 可以通过返回的 Future 来取消任务或者获取返回结果。

还可以显示地将某个指定的 Runnable 或 Callable 实例化为 FutureTask ,由于 FutureTask 类实现了 Runnable、Future 接口,因此可以将它提交给 Executor 来执行。

FutureTask 继承关系:

public class FutureTask<V> implements RunnableFuture<V> {
    ......
}
public interface RunnableFuture<V> extends Runnable, Future<V> {
    void run();
}

Future 和 FutureTask 的一个区别在于,Future 需要通过 ExecutorService 中的 submit 方法的返回值来获取结果,而 FutureTask 提交任务时不需要设置返回值,通过自身就可以获取结果。

下面来看一个计算 0~10 之间的整数之和并返回结果的例子:

import java.time.LocalDateTime;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @author :jhys
 * @date :Created in 2021/7/6 14:43
 * @Description :
 */
public class FutureTest1 {
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        System.out.println(LocalDateTime.now() + ": thread start");
        Future<Integer> future = executor.submit(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(LocalDateTime.now() + ": task start");
            int sum = 0;
            for (int i = 0; i <= 10; i++) {
                sum += i;
            }
            return sum;
        });
        executor.shutdown();
        try {
            Integer ret = future.get();
            System.out.println(LocalDateTime.now() + ": ret = " + ret);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("finish");
    }
}

输出结果:

2021-07-06T14:49:21.244: thread start

2021-07-06T14:49:24.259: task start

2021-07-06T14:49:24.259: ret = 55

finish

将上面的例子中 Future 替换为 FutureTask ,代码如下:

public class FutureTest {

    public static void main(String[] args) {

        FutureTask<Integer> future = new FutureTask<>(() -> {
            Thread.sleep(3000);
            System.out.println(LocalDateTime.now() + ": task start");

            int sum = 0;
            for (int i =0; i <= 10; i++) {
                sum += i;
            }
            return sum;
        });

        ExecutorService executor = Executors.newSingleThreadExecutor();
        // 注意这里的区别,不需要显示获取返回值
        executor.submit(future);
        executor.shutdown();

        try {
            System.out.println(LocalDateTime.now() + ": ret = " + future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("finish");
    }

}

总结

到此这篇关于Java多线程教程之如何利用Future实现携带结果任务的文章就介绍到这了,更多相关Java多线程Future实现带结果任务内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们

(0)

相关推荐

  • Java利用future及时获取多线程运行结果

    Future接口是Java标准API的一部分,在java.util.concurrent包中.Future接口是Java线程Future模式的实现,可以来进行异步计算. 有了Future就可以进行三段式的编程了,1.启动多线程任务2.处理其他事3.收集多线程任务结果.从而实现了非阻塞的任务调用.在途中遇到一个问题,那就是虽然能异步获取结果,但是Future的结果需要通过isdone来判断是否有结果,或者使用get()函数来阻塞式获取执行结果.这样就不能实时跟踪其他线程的结果状态了,所以直接使用g

  • 浅谈Java多线程处理中Future的妙用(附源码)

    java 中Future是一个未来对象,里面保存这线程处理结果,它像一个提货凭证,拿着它你可以随时去提取结果.在两种情况下,离开Future几乎很难办.一种情况是拆分订单,比如你的应用收到一个批量订单,此时如果要求最快的处理订单,那么需要并发处理,并发的结果如果收集,这个问题如果自己去编程将非常繁琐,此时可以使用CompletionService解决这个问题.CompletionService将Future收集到一个队列里,可以按结果处理完成的先后顺序进队.另外一种情况是,如果你需要并发去查询一

  • Java多线程之FutureTask的介绍及使用

    一.FutureTask的理解 FutureTask属于java.util.concurrent 包:FutureTask表示可取消的异步计算.FutureTask类提供了一个Future的基本实现 ,具有启动和取消计算的方法,查询计算是否完整,并检索计算结果.结果只能在计算完成后才能检索; 如果计算尚未完成,则get方法将阻止. 一旦计算完成,则无法重新启动或取消计算(除非使用runAndReset()调用计算 ). 二.FutureTask类图 从上面的FutureTask类图中可以看出,F

  • Java多线程之异步Future机制的原理和实现

    项目中经常有些任务需要异步(提交到线程池中)去执行,而主线程往往需要知道异步执行产生的结果,这时我们要怎么做呢?用runnable是无法实现的,我们需要用callable看下面的代码: import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurren

  • Java多线程教程之如何利用Future实现携带结果的任务

    目录 Future 介绍 Runnable Callable Future 总结 Future 介绍 Future表示异步计算的结果,它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果.Future的cancel方法可以取消任务的执行,它有一布尔参数,参数为 true 表示立即中断任务的执行,参数为 false 表示允许正在运行的任务运行完成.Future的 get 方法等待计算完成,获取计算结果. Runnable Runnable 是我们多线程开发过程中常用的接口. Exec

  • java基本教程之多线程基本概念 java多线程教程

    多线程是Java中不可避免的一个重要主体.下面我们将展开对多线程的学习.接下来的内容,是对"JDK中新增JUC包"之前的Java多线程内容的讲解,涉及到的内容包括,Object类中的wait(), notify()等接口:Thread类中的接口:synchronized关键字. 注:JUC包是指,Java.util.concurrent包,它是由Java大师Doug Lea完成并在JDK1.5版本添加到Java中的. 在进入后面章节的学习之前,先对了解一些多线程的相关概念.线程状态图

  • java基本教程之synchronized关键字 java多线程教程

    本章,会对synchronized关键字进行介绍.涉及到的内容包括:1. synchronized原理2. synchronized基本规则3. synchronized方法 和 synchronized代码块4. 实例锁 和 全局锁 1. synchronized原理 在java中,每一个对象有且仅有一个同步锁.这也意味着,同步锁是依赖于对象而存在.当我们调用某对象的synchronized方法时,就获取了该对象的同步锁.例如,synchronized(obj)就获取了"obj这个对象&quo

  • java基本教程之常用的实现多线程的两种方式 java多线程教程

    关于线程池的内容,我们以后会详细介绍:现在,先对的Thread和Runnable进行了解.本章内容包括:Thread和Runnable的简介Thread和Runnable的异同点Thread和Runnable的多线程的示例 Thread和Runnable简介Runnable 是一个接口,该接口中只包含了一个run()方法.它的定义如下: 复制代码 代码如下: public interface Runnable {    public abstract void run();} Runnable的

  • java基本教程之线程休眠 java多线程教程

    本章涉及到的内容包括:1. sleep()介绍2. sleep()示例3. sleep() 与 wait()的比较 1. sleep()介绍sleep() 定义在Thread.java中.sleep() 的作用是让当前线程休眠,即当前线程会从"运行状态"进入到"休眠(阻塞)状态".sleep()会指定休眠时间,线程休眠的时间会大于/等于该休眠时间:在线程重新被唤醒时,它会由"阻塞状态"变成"就绪状态",从而等待cpu的调度执行

  • java基本教程之线程让步 java多线程教程

    本章涉及到的内容包括:1. yield()介绍2. yield()示例3. yield() 与 wait()的比较 1. yield()介绍yield()的作用是让步.它能让当前线程由"运行状态"进入到"就绪状态",从而让其它具有相同优先级的等待线程获取执行权:但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权:也有可能是当前线程又进入到"运行状态"继续运行! 2. yield()示例下面,通过示例查看它

  • java基本教程之java线程等待与java唤醒线程 java多线程教程

    本章,会对线程等待/唤醒方法进行介绍.涉及到的内容包括:1. wait(), notify(), notifyAll()等方法介绍2. wait()和notify()3. wait(long timeout)和notify()4. wait() 和 notifyAll()5. 为什么notify(), wait()等函数定义在Object中,而不是Thread中 wait(), notify(), notifyAll()等方法介绍在Object.java中,定义了wait(), notify()

  • java基本教程之join方法详解 java多线程教程

    本章涉及到的内容包括:1. join()介绍2. join()源码分析(基于JDK1.7.0_40)3. join()示例 1. join()介绍join() 定义在Thread.java中.join() 的作用:让"主线程"等待"子线程"结束之后才能继续运行.这句话可能有点晦涩,我们还是通过例子去理解: 复制代码 代码如下: // 主线程public class Father extends Thread {    public void run() {     

  • java基本教程之Thread中start()和run()的区别 java多线程教程

    Thread类包含start()和run()方法,它们的区别是什么?本章将对此作出解答.本章内容包括:start() 和 run()的区别说明start() 和 run()的区别示例start() 和 run()相关源码(基于JDK1.7.0_40) start() 和 run()的区别说明start() : 它的作用是启动一个新线程,新线程会执行相应的run()方法.start()不能被重复调用.run()   : run()就和普通的成员方法一样,可以被重复调用.单独调用run()的话,会在

  • java多线程教程之如何使用线程池详解

    为什么要用线程池? 诸如 Web 服务器.数据库服务器.文件服务器或邮件服务器之类的许多服务器应用程序都面临处理来自某些远程来源的大量短小的任务.请求以某种方式到达服务器,这种方式可能是通过网络协议(例如 HTTP.FTP 或 POP).通过 JMS 队列或者可能通过轮询数据库.不管请求如何到达,服务器应用程序中经常出现的情况是:单个任务处理的时间很短而请求的数目却是巨大的. 只有当任务都是同类型并且相互独立时,线程池的性能才能达到最佳.如果将运行时间较长的与运行时间较短的任务混合在一起,那么除

随机推荐