Callable与Future

Callable 是一个泛型接口,里面只有一个 call() 方法,该方法可以返回泛型值 V.

        Callable<String> callable = ()->{
            //模拟子线程细节,在此睡眠5s
            //由于call方法会抛出Exception,这里的操作不用像使用Runnable的run方法那样try/catch了
            Thread.sleep(5000);
            return "Hello from Callable";
        };

Runnable 和 Callable

执行机制

Runnable既可以用在 Thread 类中,也可以用在 ExecutorService类中配合线程池的使用.

Callable 只能在 ExecutorService 中使用.

异常处理

Runnable 接口中的 run 方法签名上没有 throws,自然也就没办法向上传播受检异常.

Callable 的 call() 方法签名却有 throws,所以它可以处理受检异常.

Future

    • booleancancel(boolean mayInterruptIfRunning)

      尝试取消执行此任务。

      此方法返回后,后续调用isDone()将始终返回true 。 随后电话isCancelled()总是返回true如果此方法返回true 。 

      Vget()

      等待计算完成,然后检索其结果。

      Vget(long timeout, TimeUnit unit)

      如果需要等待最多在给定的时间计算完成,然后检索其结果(如果可用)。

      booleanisCancelled()

      如果此任务在正常完成之前被取消,则返回 true

      booleanisDone()

      返回 true如果任务已完成。

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newSingleThreadExecutor();

        //使用Callable, 可以返回值
        Callable<String> callable = ()->{
            System.out.println("进入Callable的call方法");
            //模拟子线程细节,在此睡眠2s
            //由于call方法会抛出Exception,这里的操作不用像使用Runnable的run方法那样try/catch了
            Thread.sleep(2000);

            return "Hello from Callable";
        };

        System.out.println("提交Callable到线程池");
        Future<String> future = executorService.submit(callable);

        System.out.println("主线程继续执行");

        System.out.println("主线程等待获取Future结果");

        String result = future.get();
        System.out.println("主线程获取的Future结果:"+result);

        executorService.shutdown();
    }

主线程调用 future.get() 方法会阻塞自己,直到子任务完成。我们也可以使用 Future 方法提供的 isDone 方法,它可以用来检查 task 是否已经完成.

 FutureTask

 FutureTask 实现了 RunnableFuture 接口,而 RunnableFuture 接口又分别实现了 Runnable 和 Future 接口,所以可以推断出 FutureTask 具有这两种接口的特性:

        有 Runnable 特性,所以可以用在 ExecutorService 中配合线程池使用

        有 Future 特性,所以可以从中获取到执行结果

例:

 

import java.util.concurrent.*;

public class test6 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(2);

        //创建线程1的FutureTask
        FutureTask<String> ft1 = new FutureTask<>(new T1Task());

        FutureTask<String> ft2 = new FutureTask<>(new T2Task());

        executorService.submit(ft1);
        executorService.submit(ft2);

        System.out.println(ft1.get()+ft2.get());
        System.out.println("泡好了");
        
        executorService.shutdown();

    }

    static class T1Task implements Callable<String> {

        @Override
        public String call() throws Exception {
            System.out.println("T1:洗水壶---");
            TimeUnit.SECONDS.sleep(1);
            System.out.println("T1:烧开水---");
            TimeUnit.SECONDS.sleep(15);
            return "T1:开水烧好";
        }
    }

    static class T2Task implements Callable<String>{

        @Override
        public String call() throws Exception {
            System.out.println("T2:洗茶壶---");
            TimeUnit.SECONDS.sleep(1);
            System.out.println("T2:洗茶杯---");
            TimeUnit.SECONDS.sleep(1);
            System.out.println("T2:拿茶叶");
            TimeUnit.SECONDS.sleep(2);
            return "拿到茶叶了";
        }
    }
}

上面的程序是主线程等待两个 FutureTask 的执行结果,线程1 烧开水时间更长,线程1希望在水烧开的那一刹那就可以拿到茶叶直接泡茶,怎么半呢?

那只需要在线程 1 的FutureTask 中获取 线程 2 FutureTask 的返回结果就可以了,我们稍稍修改一下程序:

import java.util.concurrent.*;

public class test6 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(2);

        //创建线程1的FutureTask
        FutureTask<String> ft2 = new FutureTask<>(new T2Task());

        FutureTask<String> ft1 = new FutureTask<>(new T1Task(ft2));

        executorService.submit(ft1);
        executorService.submit(ft2);

        System.out.println(ft1.get());
        executorService.shutdown();

    }

    static class T1Task implements Callable<String> {

        private final FutureTask<String> ft2;
        public T1Task(FutureTask<String> ft2){
            this.ft2 = ft2;
        }

        @Override
        public String call() throws Exception {
            System.out.println("T1:洗水壶---");
            TimeUnit.SECONDS.sleep(1);
            System.out.println("T1:烧开水---");
            TimeUnit.SECONDS.sleep(15);
            String r2Result = ft2.get();
            System.out.println("T2"+r2Result+", 开始泡茶");

            return "泡好了";
        }
    }

    static class T2Task implements Callable<String>{

        @Override
        public String call() throws Exception {
            System.out.println("T2:洗茶壶---");
            TimeUnit.SECONDS.sleep(1);
            System.out.println("T2:洗茶杯---");
            TimeUnit.SECONDS.sleep(1);
            System.out.println("T2:拿茶叶---");
            TimeUnit.SECONDS.sleep(2);
            return "拿到茶叶了";
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值