Java 中 Future 浅解

项目中看到使用了 Future 模式,之前没见过,就找资料了解了一下,发现挺有意思的。
前端异步有 ajax ,后台要异步就可以用 Future 模式了。
Future 模式有点类似 java 的多线程 runnable ,它们的区别就是 Runnable 里面的 run 方法是没有返回值的,而 Future 中的 call 方法有返回值。这就使得当我们的子线程有返回值,并且主线程需要使用子线程的返回结果时,Future 就能解决我们的这个问题了。

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

Future 是一个接口,使用时要用到其实现类 FutureTask。

下面是一个简单是使用示例:

package seProject;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class FutureTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        // 子线程获取一个随机数
        // callable 中的 Integer 类型,可以换成其他类型和任意对象
        Callable<Integer> starCounts = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int num = (int)(Math.random()*10 + 1);
                return num;
            }
        };
        //每次取一个随机数,并且打印对应数目的*号
        for(int c = 0; c < 5; c++) {
            FutureTask<Integer> task = new FutureTask<Integer>(starCounts);
            new Thread(task).start();
            Thread.sleep(1000);  //延迟 1s 执行下一步,要不然每次子线程没执行完就执行主线程
            if (!task.isDone()) {
                System.out.println("随机数还没确定,请耐心等待(可以调用 cancel 方法取消抽取随机数)");
                //cancel方法的参数true 代表取消该任务,返回值为 true 说明取消成功
                System.out.println(task.cancel(true));
                System.out.println(task.isCancelled());
            }
            if(!task.isCancelled()) {
                //没有被取消才继续打印*号
                int count = task.get(); //如果子线程被取消,这行将会报错
                for(int i = 0; i < count; i++) {
                    System.out.print("*");
                }
                System.out.println();
            }
        }
    }
}

上面的例子是子线程取得一个随机数,主线程获得这个随机数,并打印对应个数的*号。
当然,这个例子的效果可以直接先获取 5 个随机数,再双重循环打印对应的*号个数,上面这个例子是为了说明一下 Future 模式的用法,这里是取一个随机数,打印对应个数的星号,再取一个随机数,打印对应个数的星号;而双重循环是一次性取 5 个随机数,再一次性打印对应个数的星号。逻辑上还是不太一样的。
关于 Future 模式的更详细 更深入的理解,可以参考
官方原版解析:https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html
挖掘底层实现的大神的博客文章:http://www.cnblogs.com/cz123/p/7693064.html
大神博客文章:https://blog.csdn.net/javazejian/article/details/50896505
大神博客文章:https://blog.csdn.net/ghsau/article/details/7451464

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值