文章参考 Future 详解

1. Future?异步?

java future怎么结束 java future.get_异步编程


在线程池中,我们知道调用future.get()方法是会阻塞当前线程,知道得到get方法的返回值之后才继续运行,所以future是异步编程?线程池中的提交任务的方法有两种,一个是 execute,参数是 Runnable方法,返回值是 void方法;

java future怎么结束 java future.get_java future怎么结束_02


第二种方式是 submit方法:

java future怎么结束 java future.get_java future怎么结束_03


有三种 submit。这三种按照提交任务的类型来算分为两个类型。

提交执行 Runnable 类型的任务。

提交执行 Callable 类型的任务。

但是返回值都是 Future,这才是我们关心的东西。

在submit中可以通过传入参数得到返回值:
示例如下:

public class ThreadPoolExecutorTest {

    public static void main(String[] args) throws Exception {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 5, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10));
        AtomicInteger atomicInteger = new AtomicInteger();
        Future<AtomicInteger> future = executor.submit(() -> {
            System.out.println("测试");
            //在这里进行计算逻辑
            atomicInteger.set(5201314);
        }, atomicInteger);

        System.out.println("future的内容:" + future.get());
        Thread.currentThread().join();   //防止主线程退出
    }
}

其中调用的 get()方法是阻塞的,描述可得:

java future怎么结束 java future.get_System_04


所以总结一下这种场景下返回的 Future 的不足之处:

只有主动调用 get 方法去获取值,但是有可能值还没准备好,就阻塞等待。

任务处理过程中出现异常会把异常隐藏,封装到 Future 里面去,只有调用 get 方法的时候才知道异常了。

2. Guava 中的 Future

增加了一个监听方法,执行完成后通知!!!

public static void main(String[] args) throws InterruptedException {
        
        // 1. 初始化executor
        ListeningExecutorService executor = MoreExecutors.listeningDecorator(
                Executors.newCachedThreadPool());

        // 2. 要执行的任务
        ListenableFuture<String> listenableFuture = executor.submit(() -> {
            System.out.println(Thread.currentThread().getName() + "-女神:我开始化妆了,好了我叫你。");
            TimeUnit.SECONDS.sleep(5);
            return "化妆完毕!!";
        });

        // 3. 设置监听器函数执行回调
        listenableFuture.addListener(() -> {
            try {
                System.out.println(Thread.currentThread().getName()+"-future的内容:" + listenableFuture.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }, executor);
        // 主线程任务,不会被阻塞 
        System.out.println(Thread.currentThread().getName()+"-等女神化妆的时候可以干点自己的事情。");
        Thread.currentThread().join();
    }

另一种实现方法 FutureCallback 方式:

public class JDKThreadPoolExecutorTest {

    public static void main(String[] args) throws Exception {
        ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
        ListenableFuture<String> listenableFuture = executor.submit(() -> {
            System.out.println(Thread.currentThread().getName()+"-女神:我开始化妆了,好了我叫你。");
            TimeUnit.SECONDS.sleep(5);
            return "化妆完毕了。";
        });
        Futures.addCallback(listenableFuture, new FutureCallback<String>() {
            @Override
            public void onSuccess(@Nullable String result) {
                System.out.println(Thread.currentThread().getName()+"-future的内容:" + result);
            }

            @Override
            public void onFailure(Throwable t) {
                System.out.println(Thread.currentThread().getName()+"-女神放你鸽子了。");
                t.printStackTrace();
            }
        });
        System.out.println(Thread.currentThread().getName()+"-等女神化妆的时候可以干点自己的事情。");
        Thread.currentThread().join();
    }
}

java future怎么结束 java future.get_ide_05

JDK1.8的CompletableFuture

/**
     * JDK1.8 提供的用于异步编程, 类似于流编程
     */
    public static void testJDK8CompletableFuture(){

        CompletableFuture<Serializable> serializableCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "-女神:我开始化妆了,好了我叫你。");
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "妆化好了";
            // 处理异常
        }).handleAsync((result, exception) -> {
            if (exception != null) {
                System.out.println(Thread.currentThread().getName() + "-女神放你鸽子了!");
                return exception.getCause();
            } else {
                return result;
            }
        }).thenApplyAsync((returnStr) -> {
            System.out.println(Thread.currentThread().getName() + "-" + returnStr);
            return returnStr;
        });
        System.out.println(Thread.currentThread().getName() + "-等女神化妆的时候可以干点自己的事情。");
    }