• Callable,Runnable异同


    1、Runnable和Callable的区别

    (1) Callable规定的方法是 call(), Runnable规定的方法是 run()。

    (2) Callable的任务执行后可返回值,而 Runnable的任务是不能返回值。

    (3) call方法可以抛出异常, run方法不可以。

    (4)运行 Callable任务可以拿到一个 Future对象

      Future表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get方法来获取结果,如果线程没有执行完, Future.get()方法可能会阻塞当前线程的执行;如果线程出现异常, Future.get()会 throws InterruptedException或者 ExecutionException;如果线程已经取消,会跑出 CancellationException。取消由 cancel方法来执行。
      isDone确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。如果为了可取消性而使用 Future但又不提供可用的结果,则可以声明 Future <?> 形式类型、并返回null作为底层任务的结果。

    Future接口的定义如下:

      Future模式在请求发生时,会先产生一个 Future凭证给发出请求的客户,它的作用就像是 Proxy物件,同时,由一个新的执行线程持续进行目标物件的生成( Thread - Per - Message),真正的目标物件生成之后,将之设定至 Future之中,而当客户端真正需要目标物件时,目标物件也已经准备好,可以让客户提取使用。

          结合 JDK的 Future来看,就是你 run线程后,你可以把线程的返回值赋给 Future并返回一个 Future对象。这时你可以立即拿到这个对象,然后进行下面的逻辑。但是如果你要 get这个 Future中的线程结果,就会被阻塞直到线程结束。

      相当于现在的期房,你把手续和钱都交上去了,就可以马上拿到合同,但只有合同没有房子。这个时候你已经是有房一族了,你可以先去买家电买装修(走下面的其他逻辑)。但是你要把家电和装修放进去,就必须等到房子完工(阻塞)。

    2、Callable实现:

      submit方法会产生Future对象,它用Callable返回结果的特定类型进行了参数化,可以用isDone()的方法来查询Future是否已经完成。当任务完成是,它具有一个结果,可以调用get()方法来获取该结果。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    package zeze;
      
    import java.util.ArrayList;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
      
    /***
     *
     * @ClassName: EbayMultiplyThreadCheck
     * @Description: TODO
     * @author zeze
     * @date 2017年2月16日 上午8:49:46
     *
     */
    public class EbayMultiplyThreadCheck {
        public static void main(String[] args) {
            ExecutorService exec = Executors.newFixedThreadPool(10);
            ArrayList<Future<String>> results = new ArrayList<Future<String>>();
      
            for (int i = 0; i < 10; i++) {
                String email = "asd" + i + "@qq.com";
                results.add(exec.submit(new TaskWithResult(email)));
            }
      
            boolean isDone = false;
            while (!isDone) {
                isDone = true;
                for (Future<String> future : results) {
                    if (!future.isDone()) {
                        isDone = false;
                        try {
                            Thread.sleep(1000);
                        catch (InterruptedException e) {
                        }
                        break;
                    }
                }
            }
            exec.shutdown();
        }
    }
      
    class TaskWithResult implements Callable<String> {
      
        private String email;
      
        public TaskWithResult(String email) {
            this.email = email;
        }
      
        @Override
        public String call() {
            System.out.println(email);
            return null;
        }
      
    }

    3、Runnable 实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    /** 
    * @Title: RunnableDemo.java
    * @Package zeze
    * @Description: TODO(用一句话描述该文件做什么)
    * @author A18ccms A18ccms_gmail_com 
    * @date 2017年3月13日 下午4:08:09
    * @version V1.0 
    */
    package zeze;
      
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
      
    import javafx.animation.Animation.Status;
      
    /**
     * @ClassName: RunnableDemo
     * @Description: TODO
     * @author zeze
     * @date 2017年3月13日 下午4:08:09
     *
     */
    public class RunnableDemo implements Runnable {
      
        protected int countDown = 10;
        private static int taskCount = 0;
        private final int id = taskCount++;
      
        public RunnableDemo() {
        }
      
        public RunnableDemo(int countDown) {
            this.countDown = countDown;
        }
      
        public String status() {
            return "#" + id + "(" + (countDown > 0 ? countDown : "LiftOff!") + ").";
        }
      
        @Override
        public void run() {
            while (countDown-- > 0) {
                System.out.print(status());
                Thread.yield();// 将CPU从一个线程转移给另一个线程
            }
        }
      
        public static void main(String[] args) {
      
            System.out.println("这个任务的run()不是单独的线程驱动,是在main()中直接调用");
            RunnableDemo launch = new RunnableDemo();
            launch.run();
            System.out.println();
            System.out.println("************************************");
      
            System.out.println("在新线程中启动任务");
            Thread thread = new Thread(new RunnableDemo());
            thread.start();
            System.out.println("Waiting for LiftOff");
            System.out.println("************************************");
      
            System.out.println("添加多个线程去驱动更多的任务");
            for (int i = 0; i < 5; i++) {
                new Thread(new RunnableDemo()).start();
            }
            System.out.println("Waiting for LiftOff");
      
            System.out.println("************************************");
            System.out.println("使用executor");
            ExecutorService exec = Executors.newCachedThreadPool();
            exec=Executors.newFixedThreadPool(5);
            for (int i = 0; i < 5; i++) {
                exec.execute(new RunnableDemo());
            }
            exec.shutdown();
        }
      
    }
  • 相关阅读:
    Day03 小程序代码构成 -------4月19日
    Day02 申请账号和下载微信开发者工具------4月19日
    Day01《起步》 --- 4月19日
    记录EFCORE命令行操作数据库的方式
    关于Angular+ngx-perfect-scrollbar自定义各大浏览器滚动条样式的解决方法
    Angular里使用(image-compressor.js)图片压缩
    moment的简单使用方式
    关于Npoi+excel文件读取,修改文件内容的处理方式
    记录sql中统计近五天数据的口径(While+IF)
    Angular中ngx-image-cropper图片裁剪的使用
  • 原文地址:https://www.cnblogs.com/DreamRecorder/p/9257126.html
Copyright © 2020-2023  润新知