Future和Callable

除了线程池可以治理线程外,Future和Callable也可以治理线程。

Runnable缺陷

  Runnable的run无返回值

  不能抛出Checked Exception

  我们通过下面实例去演示。

  

   我们思考下为什么没有返回值呢?一般调用Runnable的类为Thread,Thread是JDK提供,我们无法做处理。

  Callable接口提供了返回值。

Callable接口

  Callable接口是可以有返回值和异常的,如下源码所示:

  

Feature类

  Future可搭配Callable来使用。Feature是一个存储器

Future与Callable关系

  我们可以通过Future的get方法来获取Callable接口执行的返回值;

  我们可以通过Feature的isDone方法来判断Callable是否已经执行结束了,也可以取消这个任务。

  call未执行完之前,用Feature的get时会阻塞,直到有返回结果

Future主要方法

  主要方法如下:

  1.get 任务执行完成了,则直接返回;任务未完成,get方法会进行阻塞直到任务完成;任务执行过程中抛出了异常时,get方法也会抛出异常,get只抛出ExecutionException;

    任务取消时,get抛出CancellationException异常;任务超时时,抛出TimeoutException

  2.get(long timeout,TimeUnit unit) 有超时的获取,参照上方法

  3.cancel 取消任务执行;取消策略需要关注

  4.isDone 判断线程是否执行完毕,执行完毕不代表成功执行。

  5.isCancelled 是否取消

  

 Future基本用法实例

       我们给线程池提供一个任务,获取对应Future,见如下代码所示:

  

package com.yang.callable;

import java.util.Random;
import java.util.concurrent.*;

public class OneFutureDemo {
    public static void main(String[] args) {
        ExecutorService executorService= Executors.newFixedThreadPool(10);
        Future<Integer> future = executorService.submit(new CallableTask<Integer>());
        try {
            System.out.println(future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        executorService.shutdown();
    }
    
    static class CallableTask<I extends Number> implements Callable<Integer>{
        @Override
        public Integer call() throws Exception {
            Thread.sleep(1000);
            return new Random().nextInt();
        }
    }
    
}

  运行结果如下所示:

  

FutureLamda实例

  我们使用Lamda来实现,请看下代码:

  

package com.yang.callable;

import java.util.Random;
import java.util.concurrent.*;

public class FutureLamdaDemo {
    public static void main(String[] args) {
        ExecutorService executorService= Executors.newFixedThreadPool(10);
        Callable<Integer> callable=()->{
          Thread.sleep(3000);
          return new Random().nextInt();
        };
        Future<Integer> future = executorService.submit(callable);
        try {
            System.out.println(future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        executorService.shutdown();
    }
    

    
}

  

Future批量接收实例代码

  Future批量接收Callable,实例代码如下所示:

  

package com.yang.callable;

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

public class MultiFutureDemo {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        ArrayList<Future<Integer>> futureArrayList = new ArrayList<Future<Integer>>();
        for (int i = 0; i < 10; i++) {
            futureArrayList.add(executorService.submit(new CallableTask()));
        }

        for (int i = 0; i < 10; i++) {
            try {
                Integer integer = futureArrayList.get(i).get();
                System.out.println(integer);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
    static class CallableTask implements Callable<Integer>{
        @Override
        public Integer call() throws Exception {
            Thread.sleep(3000);
            return new Random().nextInt();
        }
    }
}

  运行结果如下所示:

  

 Future在执行过程中抛出了异常实例

  本实例演示get方法抛出了异常,实例代码如下所示:

  

package com.yang.callable;

import java.util.concurrent.*;

public class GetExecption {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        Future<Integer> future=executorService.submit(new CallableTask());
        try{
            future.get();
        }catch (IllegalArgumentException e){
            System.out.println("线程内部抛出异常");
        }catch (ExecutionException e){
            System.out.println("执行过程中抛出异常");
        } catch (InterruptedException e) {
            e.printStackTrace();
            System.out.println("中断异常");
        }
    }
    static class CallableTask implements Callable<Integer>{
        @Override
        public Integer call() throws Exception {
            throw new IllegalArgumentException("不合法的参数异常");
        }
    }
}

  执行结果如下:

  

Future的isDone实例

  isDone演示如下所示:

  

package com.yang.callable;

import java.util.concurrent.*;

public class GetExecption {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        Future<Integer> future=executorService.submit(new CallableTask());
        try{
            future.get();
        }catch (IllegalArgumentException e){
            System.out.println("线程内部抛出异常");
        }catch (ExecutionException e){
            System.out.println("执行过程中抛出异常");
        } catch (InterruptedException e) {
            e.printStackTrace();
            System.out.println("中断异常");
        }
        System.out.println(future.isDone());

    }
    static class CallableTask implements Callable<Integer>{
        @Override
        public Integer call() throws Exception {
            throw new IllegalArgumentException("不合法的参数异常");
        }
    }
}

  运行结果

  

 Future获取任务超时实例

  本实例演示get的超时方法,当超时后,我们取消这个任务。我们同事演示下cancel方法传入true或者false

  

package com.yang.callable;

import java.util.Calendar;
import java.util.concurrent.*;

/**
 * 本实例演示Future超时
 */
public class TimeoutFutureDemo {
    private static String defaultAdStr = "我是默认的";

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        Future<String> future = executorService.submit(new FutureTask());
        try {
            String s = future.get(2000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            System.out.println("中断了");
        } catch (ExecutionException e) {
            System.out.println("执行异常");
        } catch (TimeoutException e) {
            System.out.println("超时了");
            //控制是否要中断,true:允许中断
            boolean cancelStatus = future.cancel(true);
            System.out.println(cancelStatus);
        }
    }


    static class FutureTask implements Callable<String> {
        @Override
        public String call() throws Exception {

            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                System.out.println("中断了,返回默认的");
                return defaultAdStr;
            }
            return "外部获取的消息";
        }
    }
}

  运行结果如下所示:

  

   Cancel方法的总结

  1.cancel方法支持传入true和false

  2.当传入true时,需要考虑当前线程是否支持中断,中断后的业务逻辑是否正确

  3.任务都已经开始,我们是否需要其执行完毕,需要则用false

     

  

  

  

原文地址:https://www.cnblogs.com/cnxieyang/p/12779349.html