[JAVA多线程并发]Callable、Future、invokeAll和invokeAny(二)

上一篇博客

文章目录

  • 三、Callable和Future
    • 1、Callable
    • 2、Future
    • 3、invokeAll
    • 4、invokeAny

三、Callable和Future

1、Callable

CallableRunnable非常相似,其只有一个Call()方法,区别在于其有返回值并且可以抛出checked异常。

import java.util.concurrent.*;

public class Application {

    public static void main(String[] args) {
        Callable callable = new Callable() {
            @Override
            public Object call() throws Exception {
                Thread.sleep(1000);
                return "返回值";
            }
        };
    }
}

可见这里的Thread.sleep()没有try/catch。

2、Future

就像Runnable一样,Callable也可以提交给Executor执行。但是我们不知道被提交的任务在何时可以获取到它的执行结果。因此,其执行返回一个叫Future的特殊类型值。Future被用于获取任务执行结果(当结果可以被获取时)。
Future有些类似于Javascript中的Promise

package com;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author peng fei
 * @since 2020-07-20 14:53
 */

public class ThreadApplication {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Callable<String> callable1 = new Callable<String>() {
            @Override
            public String call() throws Exception {
                Thread.sleep(2000L);
                return "Done1";
            }
        };

        Callable<String> callable2 = new Callable<String>() {
            @Override
            public String call() throws Exception {
                Thread.sleep(3000L);
                return "Done2";
            }
        };

        FutureTask<String> futureTask = new FutureTask<>(callable1);
        Thread thread = new Thread(futureTask);
        thread.start();
        while(!futureTask.isDone()){
        }
        System.out.println(futureTask.get());
        System.out.println("------------");

        Future<String> future1 = executorService.submit(callable1);
        Long start = System.currentTimeMillis();
        while(!future1.isDone()) {
            String time = (System.currentTimeMillis() - start) + "ms";
            System.out.print(time);
            StringBuilder backspace = new StringBuilder();
            for (int i = 0;i < time.length();i ++) {
                backspace.append("\b");
            }
            System.out.print(backspace.toString());
        }
        System.out.println(future1.get());
        System.out.println(System.currentTimeMillis() - start + "ms");

        System.out.println("---------------------");
        List<Callable<String>> callableList = new ArrayList<>();
        callableList.add(callable1);
        callableList.add(callable2);
        List<Future<String>> futures = executorService.invokeAll(callableList);
        for (Future<String> future : futures) {
            System.out.println(future.get());
        }
        System.out.println(System.currentTimeMillis() - start + "ms");


        System.out.println("---------------------");
        String result = executorService.invokeAny(callableList);
        System.out.println(result);
        System.out.println(System.currentTimeMillis() - start + "ms");
    }
}

console:
[JAVA多线程并发]Callable、Future、invokeAll和invokeAny(二)_第1张图片

  • FutureTask实现了RunnableFuture extend Runnable, Future接口,用于Callable任务线程执行
  • future.isDone()用于判断Callable是否完成调度执行
  • future.cancel()用于取消Callable的执行,当无参数时,线程将会将正在执行中的Callable执行结束。当future.cancel(true)时,将会终止正在执行中的线程,从而在get是出发异常。
  • future.get()用于得到执行Callable的结果,该方法无参数时将会一直阻塞程序,直到执行完毕得到结果。
  • 有时候会遇到调用远程服务的情况(remote service) - 这时需要通过设置超时时间来解决,例如future.get(1, TimeUnit.SECONDS),当阻塞1秒后还无法得到结果,就会抛出异常:
    在这里插入图片描述

3、invokeAll

  • List> futures = executorService.invokeAll(callableList);其会阻塞程序,直至所有的Callable任务全部执行完成,并返回future的List。

4、invokeAny

  • String result = executorService.invokeAny(callableList);其会返回最先执行完的Callable的结果。

你可能感兴趣的:(JAVASE)