使用解析
1、首先查看官方文档和源码是如何讲解的
可以知道以下几点:
1、Callable接口类似于Runnable接口
2、Callable有返回值
3、Callable可以抛出异常
4、调用call()方法
5、Callable支持泛型
2、既然和Runnable接口类似,就直接创建一下
class MyThread implements Callable<String>{ @Override public String call() throws Exception { System.out.println("call()"); return "123"; } }
3、重点:如何启动呢?
要知道线程的启动只能通过 new Thread().start()
那该怎么办?
现在知道的是Thread类,和Runnable接口有关系,我们是否可以通过Runnable接口和Thread类挂上关系呢?
通过图解拆分关系
-
现在你是Callable接口,Runnable接口是的女朋友,Thread类是你女朋友的闺蜜
-
而现在你想认识你女朋友的闺蜜,怎么办呢?
-
如果你直接去找你女朋友的闺蜜,肯定会有些突兀或者造成误会!
-
肯定需要通过你女朋友的介绍,对吧!
-
那么你的女朋友要如何介绍呢?这是一个问题!
4、查看Runnable接口在文档中的说明
Runnable接口本身没有说明好看的,只是一个函数式接口,里面有个run()
方法,仅此而已!
但是它有两个重要的实现类,图中已经标出:
往下翻,在构造器中你会发现可以丢入一个Callable接口
那么现在就可以通过FutureTask实现类和Thread类挂上关系了!
具体使用
有两个坑,需要注意返回参数和缓存
创建Callable线程并启动
package com.zxh.callable; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; public class CallableTest { public static void main(String[] args) { MyThread myThread = new MyThread(); FutureTask futureTask = new FutureTask(myThread); // 适配器类 new Thread(futureTask).start(); } } class MyThread implements Callable<String>{ @Override public String call() throws Exception { System.out.println("call()"); return "123"; } }
Callable返回的参数和注意点
获取返回的参数
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class CallableTest { public static void main(String[] args) throws ExecutionException, InterruptedException { MyThread myThread = new MyThread(); FutureTask futureTask = new FutureTask(myThread); // 适配器类 new Thread(futureTask).start(); Object o = futureTask.get(); System.out.println(o); } } class MyThread implements Callable<String>{ @Override public String call() throws Exception { System.out.println("call()"); return "123"; } }
注意点
futureTask.get()
方法可能会阻塞
因为call()
中可能会存在耗时的任务,所以在获取返回值的时候,就会等待(阻塞)。
-
当你使用两个线程调用的时候,会发现输出只有1次。
-
因为结果被缓存,提高了效率
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class CallableTest { public static void main(String[] args) throws ExecutionException, InterruptedException { MyThread myThread = new MyThread(); FutureTask futureTask = new FutureTask(myThread); // 适配器类 new Thread(futureTask, "A").start(); new Thread(futureTask, "B").start(); //结果会被缓存 Object o = futureTask.get(); // 会阻塞,一般通过异步操作 System.out.println(o); } } class MyThread implements Callable<String>{ @Override public String call() throws Exception { System.out.println("call()"); return "123"; } }