• 说说Runnable与Callable


    Callable接口:

    1 public interface Callable<V> {
    2     V call() throws Exception;
    3 }

    Runnable接口:

    public interface Runnable {
        public abstract void run();
    }

    相同点:

    1. 两者都是接口;(废话)
    2. 两者都可用来编写多线程程序;
    3. 两者都需要调用Thread.start()启动线程;

    不同点:

    1. 两者最大的不同点是:实现Callable接口的任务线程能返回执行结果;而实现Runnable接口的任务线程不能返回结果;
    2. Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛;

    注意点:

    • Callable接口支持返回执行结果,此时需要调用FutureTask.get()方法实现,此方法会阻塞主线程直到获取‘将来’结果;当不调用此方法时,主线程不会阻塞!

    Callable工作的Demo:

     1 package com.callable.runnable;
     2 
     3 import java.util.concurrent.Callable;
     4 import java.util.concurrent.ExecutionException;
     5 import java.util.concurrent.FutureTask;
     6 
     7 /**
     8  * Created on 2016/5/18.
     9  */
    10 public class CallableImpl implements Callable<String> {
    11 
    12     public CallableImpl(String acceptStr) {
    13         this.acceptStr = acceptStr;
    14     }
    15 
    16     private String acceptStr;
    17 
    18     @Override
    19     public String call() throws Exception {
    20         // 任务阻塞 1 秒
    21         Thread.sleep(1000);
    22         return this.acceptStr + " append some chars and return it!";
    23     }
    24 
    25 
    26     public static void main(String[] args) throws ExecutionException, InterruptedException {
    27         Callable<String> callable = new CallableImpl("my callable test!");
    28         FutureTask<String> task = new FutureTask<>(callable);
    29         long beginTime = System.currentTimeMillis();
    30         // 创建线程
    31         new Thread(task).start();
    32         // 调用get()阻塞主线程,反之,线程不会阻塞
    33         String result = task.get();
    34         long endTime = System.currentTimeMillis();
    35         System.out.println("hello : " + result);
    36         System.out.println("cast : " + (endTime - beginTime) / 1000 + " second!");
    37     }
    38 }

    测试结果:

    hello : my callable test! append some chars and return it!
    cast : 1 second!
    
    Process finished with exit code 0

    Runnable工作的Demo:

     1 package com.callable.runnable;
     2 
     3 /**
     4  * Created on 2016/5/18.
     5  */
     6 public class RunnableImpl implements Runnable {
     7 
     8     public RunnableImpl(String acceptStr) {
     9         this.acceptStr = acceptStr;
    10     }
    11 
    12     private String acceptStr;
    13 
    14     @Override
    15     public void run() {
    16         try {
    17             // 线程阻塞 1 秒,此时有异常产生,只能在方法内部消化,无法上抛
    18             Thread.sleep(1000);
    19         } catch (InterruptedException e) {
    20             e.printStackTrace();
    21         }
    22         // 最终处理结果无法返回
    23         System.out.println("hello : " + this.acceptStr);
    24     }
    25 
    26 
    27     public static void main(String[] args) {
    28         Runnable runnable = new RunnableImpl("my runable test!");
    29         long beginTime = System.currentTimeMillis();
    30         new Thread(runnable).start();
    31         long endTime = System.currentTimeMillis();
    32         System.out.println("cast : " + (endTime - beginTime) / 1000 + " second!");
    33     }
    34 }

    测试结果:

    cast : 0 second!
    hello : my runable test!
    
    Process finished with exit code 0

    写此篇的原因是一次面试中问到Callable与Runnable的区别,当时用的多的是Runnable,而Callable使用很少!

    比较了两者后(网上查了不少),发现Callable在很多特殊的场景下还是很有用的!最后留点抄的代码,加深对Callable的认识!

     1 package com.inte.fork;
     2 
     3 /**
     4  * Created on 2016/4/20.
     5  */
     6 
     7 import java.util.*;
     8 import java.util.concurrent.*;
     9 
    10 import static java.util.Arrays.asList;
    11 
    12 public class Sums {
    13 
    14     static class Sum implements Callable<Long> {
    15         private final long from;
    16         private final long to;
    17 
    18         Sum(long from, long to) {
    19             this.from = from;
    20             this.to = to;
    21         }
    22 
    23         @Override
    24         public Long call() {
    25             long acc = 0;
    26             for (long i = from; i <= to; i++) {
    27                 acc = acc + i;
    28             }
    29             System.out.println(Thread.currentThread().getName() + " : " + acc);
    30             return acc;
    31         }
    32     }
    33 
    34     public static void main(String[] args) throws Exception {
    35         ExecutorService executor = Executors.newFixedThreadPool(3);
    36         List<Future<Long>> results = executor.invokeAll(asList(
    37                 new Sum(0, 10), new Sum(0, 1_000), new Sum(0, 1_000_000)
    38         ));
    39         executor.shutdown();
    40 
    41         for (Future<Long> result : results) {
    42             System.out.println(result.get());
    43         }
    44     }
    45 }

    本文转自:https://www.cnblogs.com/frinder6/p/5507082.html

  • 相关阅读:
    [置顶] Codeforces Round #198 (Div. 1)(A,B,C,D)
    Python基础 1----Python语言基础和Python环境准备与安装
    UVa 10400
    Linux多线程——使用互斥量同步线程
    SICP 习题 (1.8) 解题总结
    浙江大学PAT上机题解析之1014. 福尔摩斯的约会 (20)
    3.11 程序改错
    汉语-汉字:芔
    汉语-汉字:屮
    汉语-汉字:艸
  • 原文地址:https://www.cnblogs.com/jasonZh/p/8965869.html
Copyright © 2020-2023  润新知