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

    技术2022-07-11  75

    上一篇博客

    文章目录

    三、Callable和Future1、Callable2、Future3、invokeAll4、invokeAny

    三、Callable和Future

    1、Callable

    Callable与Runnable非常相似,其只有一个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:

    FutureTask<T>实现了RunnableFuture<T> extend Runnable, Future<V>接口,用于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<Future<String>> futures = executorService.invokeAll(callableList);其会阻塞程序,直至所有的Callable任务全部执行完成,并返回future的List。

    4、invokeAny

    String result = executorService.invokeAny(callableList);其会返回最先执行完的Callable的结果。
    Processed: 0.011, SQL: 9