zoukankan      html  css  js  c++  java
  • 简单理解Callable接口

    Callable接口:

      Callable,新启线程的一种方式,返回结果并且可能抛出异常的任务,在前面的新启线程的文章中用过,但是没有具体讲解

      优点:

        可以获取线程的执行结果,也称为返回值

        通过与Future的结合,可以实现利用Future来跟踪异步计算的结果

    Runnable和Callable的区别:

      Callable规定的方法是call(),Runnable规定的接口是run();

      Callable的任务执行后可返回值,而Runnable的任务是不能有返回值的;

      call方法可以抛出异常,run方法不可以

      运行Callable任务可以拿到一个Future对象,表示异步计算的结果,它提供了检查是否计算完成的方法,以等待计算的完成,并检索计算的结果,通过Future对象可以了解任务执行情况,可以取消任务的执行,还可以获取执行结果

    Future接口:

      Future是一个接口,代表了一个异步计算的结果,接口中的方法用来检查计算是否完成,等待完成和得到计算结果;

      当计算完成后,只能通过get()方法得到结果,get()方法会阻塞,一直到线程的计算结果完成并返回;

      如果想取消,那么调用cancel()方法,其他方法用于确定任务是正常完成还是取消了;

      一旦计算完成了,那么这个计算就不能被取消

    FutureTask类:

      FutureTask类实现了RunnableFuture接口,而RunnableFuture接口是继承了Runnable和Future接口,所以说FutureTask是一个提供异步计算结果的任务;

      FutureTask可以用来包装Callable或者Runnable接口的实现对象,因为FutureTask实现了Runnable接口,所以FutureTask也可以提交给线程池

    Callable,Future,FutureTask三者之间的关系:

    Callable的两种执行方式:

    1:借助FutureTask,包装Callable接口的实现类,然后传递给Thread线程执行

    package org.dance.day2.future;
    
    import org.dance.tools.SleepTools;
    
    import java.util.Random;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    /**
     * Callable的两种执行方式
     * @author ZYGisComputer
     */
    public class UseCallable {
    
        /**
         * 实现Callable接口的线程
         */
        private static class UseCall implements Callable<Integer>{
    
            private int sum;
    
            @Override
            public Integer call() throws Exception {
                System.out.println("callable子线程开始执行任务计算");
                Thread.sleep(2000);
                for (int i = 0; i < 5000; i++) {
                    sum += i;
                }
                System.out.println("子线程任务计算完成,返回值:"+sum);
                return sum;
            }
        }
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
    
            UseCall useCall = new UseCall();
    
            // 使用FutureTask包装
            FutureTask<Integer> futureTask = new FutureTask<>(useCall);
    
            // 包装为Thread
            Thread thread = new Thread(futureTask);
    
            thread.start();
    
            // 开始主线程的任务
            Random random = new Random();
    
            SleepTools.second(1);
    
            if(random.nextBoolean()){
                System.out.println("获取Callable result:"+futureTask.get());
            }else{
                System.out.println("中断计算");
                // 中断计算,取消线程的执行
                futureTask.cancel(true);
            }
        }
    
    }

    2:借助线程池来执行

    UseCall useCall = new UseCall();
     // 创建一个线程池
    ExecutorService executorService = Executors.newCachedThreadPool();
    Future<Integer> future = executorService.submit(useCall);

    线程池这个只粘贴关键代码,线程池的知识就不在这多说了,之后会具体讲解

    返回的Future接口的使用和FutureTask是一样的

    这个接口实现的线程,是有返回值的

    可以说一下我之前用到的场景

    是这样的,我之前用到的一般是用于云上,或者存储服务器下载电子文件,就是本身我一个接口就是需要查询数据库并,进行结果的大量计算和结果转换的,同时还要上云上下载比较大的电子文件,所以我采用Callable配合线程池来完成云上文件的下载;

    作者:彼岸舞

    时间:2020104

    内容关于:并发编程

    本文来源于网络,只做技术分享,一概不负任何责任

  • 相关阅读:
    洛古模拟赛--星空
    bzoj4476 [Jsoi2015]送礼物
    矩阵乘法总结
    bzoj 3167 SAO
    codeforces 671D
    10.28
    noip前集训
    10.2晚 模拟继续
    10.2 考试
    10.1 国庆 考试
  • 原文地址:https://www.cnblogs.com/flower-dance/p/13740315.html
Copyright © 2011-2022 走看看