本章主要学习Callable接口。
Callable接口是一种能够返回计算结果并且可以抛出异常的任务。
Callable接口的实现类需要定义一个无参数的方法:call()。
@FunctionalInterface public interface Callable<V> { /** * Computes a result, or throws an exception if unable to do so. * * @return computed result * @throws Exception if unable to compute a result */ V call() throws Exception; }
Callable接口与Runnable接口类似,都是为了实现多线程而设计的。
但是,Runnable接口并不能返回结果,也不能抛出一个可检查的异常。
Executors工具类包含一些工具方法,这些方法能够将一些其他常见的形式转换成Callable接口的实现类。
关于这些转换方法,可以参考后续文章。
2.Callable与Runnable对比
类似之处:
都是为了实现多线程而设计的
都可以在Executor框架中使用
区别之处:
Callable接口可以返回结果;Runnable接口不能返回结果
Callable接口可以抛出异常;Runnable接口不能抛出异常
Callable接口是泛型接口;Runnable接口是普通接口
Callable接口常常与Future结合使用
3.实例练习
练习目的:
加深对Callable接口和Runnable接口的理解。
了解两种多线程编程方式的区别:Thread和Executor。
了解Callable 和Future 的基本用法,理解返回结果的优势。
练习说明:
分别以下面三种方式实现随机数的获取:
1.Runnable + Thread
2.Runnable + Executor
3.Callable + Future + Executor
实例代码:
Runnable编程方式:
/** * 多线程示例-获取随机值-实现Runnable接口 */ //定义一个共享变量 static AtomicInteger value = new AtomicInteger(0); //实现Runnable static class RandomByRunnable implements Runnable{ @Override public void run() { //模拟计算 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //CAS赋值 value.compareAndSet(0,RandomUtils.nextInt(100,200)); } }
Callable编程方式:
/** * 多线程示例-获取随机值-实现Callable接口 */ static class RandomByCallable implements Callable<Integer>{ @Override public Integer call() throws Exception { Thread.sleep(1000); return RandomUtils.nextInt(100,200); } }
三种多线程方式:
/** * <p>Callable与Runnable接口的对比</p> * @author hanchao 2018/4/2 22:15 **/ public static void main(String[] args) throws Exception { //实现Runnable接口的方式 new Thread(new RandomByRunnable()).start(); //通过while去循环查询是否获取了值 while (value.get() == 0); System.out.println("实现Runnable接口的线程(裸线程),获取了结果:" + value.get()); //实现Runnable接口 + Executor框架的方式 ExecutorService executorService = Executors.newCachedThreadPool(); //重新初始化 value = new AtomicInteger(0); executorService.submit(new RandomByRunnable()); //通过while去循环查询是否获取了值 while (value.get() == 0); System.out.println("实现Runnable接口的线程 + Executor框架,获取了结果:" + value.get()); //实现Callable接口 + Executor框架 Future<Integer> result = executorService.submit(new RandomByCallable()); System.out.println("实现Callable接口 + Executor框架,获取了结果:" + result.get()); executorService.shutdown(); }
运行结果:
实现Runnable接口的线程(裸线程),获取了结果:175 实现Runnable接口的线程 + Executor框架,获取了结果:163 实现Callable接口 + Executor框架,获取了结果:162