java future用法_Java中的Future

3a9e73d214087159b1ae3ca19e7aae4f.png

不知道别人的习惯是如何的,就我个人来说,写程序一般不是有性能问题,很少主动去使用多线程程序。除了主动去优化的场景,直观地认为多线程还是比较麻烦,可能涉及到同步问题,而且一个线程挂了,连累整个进程挂掉。除了可能快点外,多线程没啥大的优点。这样的想法也浪费不少可以优化程序的地方。

Java 中的 Future 用的不算多,知道是 Java 多线程时候保存返回结果的,这两天学习了 Java 并发编程,学到了这个,顺便纪录下,印象会深刻点。

一 Future 是什么

我们写多线程程序的时候,任务进程是实现了Runnable接口,或者直接写个类继承Thread,但是如果我们需要任务执行完成后,给出个结果,以上两种方式只能通过写共享对象或文件来实现目的,无法直接返回。

还有个缺点,就是Runnable接口中的run方法无法抛出异常,我们可能想任务在处理过程中抛出异常,但是Runnable接口无法抛出异常,就算抛出异常了,我们在哪里接收那,run接口不是通过主动调用的。

为解决以上两个问题,java 中定义了Callable接口,接口的具体定义如下:

public interface Callable<V> {
     V call() throws Exception;
}

直接了返回值和可以抛出异常,但是这里面就有问题了:

  1. 抛出的异常我们如何接收?
  2. 返回值我们如何接收,如果每个都有返回值,都需要等待子线程执行完毕,那这个多线程变成同步的了,也没啥意义了。

这就是 Future 需要存在的意义了。Future是 Java 的接口,类似于容器保存了Callable的返回结果。我们把子任务放入线程池之后,直接返回,进行其他处理,然后再调用Future的 get 方法来获取结果,Future还可以控制子任务的执行。

二 Future 接口方法说明

接口定义如下:

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

get 方法说明:

  • 如果任务执行完毕了,直接返回执行结果。
  • 如果没有执行完成, 则进行阻塞。
  • 如果抛出了异常,则 get 也抛出 ExecutionException 异常。
  • 如果任务被取消了,则抛出 CancellationException 异常。
  • 如果使用 get 带了时间,在规定时间返回结果则正常,如果没有在规定的时间返回结果,则抛出 TimeoutException 异常。

isDone方法说明:

  • 任务执行完毕返回 true,程序执行失败仍然会返回 true。
  • 未执行完毕返回 false。

cancel 方法说明:

  • 任务未被执行情况下,取消返回 true,被正常取消。
  • 任务被执行,且执行结束情况下,取消失败,返回 false。
  • 如果任务在执行中,如果 cancel 传入 true,则标识中断正在执行的任务 ,传入 false 标识不中断正在执行的任务,等正在执行的任务执行结束,返回 false。

isCancelled方法说明:

  • 判断任务是否被取消。

三 实践

3.1 一般用法

import java.util.concurrent.*;

public class ExceptionFuture {
    static class CallableTask implements Callable<Integer> {
        @Override
        public Integer call() throws  Exception {
            throw new IllegalArgumentException("异常测试");
        }
    }
    public static void main(String [] args) {
        ExecutorService service = Executors.newFixedThreadPool(10);
        Future<Integer> future = service.submit(new CallableTask());
        try {
            for (int i = 0; i < 6; i++) {
                System.out.println(i);
                Thread.sleep(800);
            }
            System.out.println(future.isDone());
            System.out.println("over");
            future.get();
        }catch(InterruptedException e) {
            e.printStackTrace();
        }catch(ExecutionException e) {
            e.printStackTrace();
        }
        service.shutdown();
    }
}

代码执行结果:

29d113a0c28af15d974add32f136c124.png

说明:

  1. 任务中的异常类型会变成 ExecutionException 异常,不过里面带有原来异常信息。
  2. Thread.sleep(800)是为了让子线程执行完任务,实际使用中我们可以先执行其他任务,执行一段代码后,再去 get,提升整体的 cpu 利用率。

3.2 FutureTask 创建 Future

FutureTask 比较神奇,既可以做为Future 保存执行的结果,又可以作为Task来传入线程池作为任务执行。

029b1a582d5285803864fd5c81c9bf9d.png

说明:

  • 1.因为 FutureTask 继承的接口,实现了 Runnable ,所以可以执行;又实现了 Future 所以可以保存结果。

实例代码:

import org.activiti.engine.runtime.Execution;
import javax.jws.Oneway;
import java.util.concurrent.*;

class Task implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        System.out.println("开始计算任务");
        int sum = 0;
        for (int i = 0; i <1000; i++) {
            sum += i;
        }
        return sum;
    }
}



public class FutureTaskTest {

    public  static void main(String [] args) throws InterruptedException, ExecutionException {
        Task task = new Task();
        Callable callable;
        FutureTask<Integer> futureTask = new FutureTask<>(task);
        ExecutorService executorService = Executors.newFixedThreadPool(4);
        // new Thread(futureTask).start();
        executorService.submit(futureTask);
        System.out.println("sleep and wait");
        Thread.sleep(10000);
        System.out.println(futureTask.get());
        executorService.shutdown();
    }
}

执行结果:

dd23f7b63507856433543c14d33f1c4f.png

四 诗词欣赏

 离思五首·其四

[唐代] [元稹]
曾经沧海难为水,除却巫山不是云。
取次花丛懒回顾,半缘修道半缘君。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值