1.Callable接口简介
2.FutureTask类简介
3.Callable接口使用
1.Callable接口简介
在介绍Callable接口之前,我们先回顾一下我们很熟悉的Runnable接口:
我们想要使用线程的时候,很多时候都是先实现Runnable接口,然后重写run方法,如下所示:
public class RunnableDemo implements Runnable {
@Override
public void run() {}
}
【JAVA并发编程——Callable接口和FutureTask简介和使用】不难发现,我们一直使用的Runnable接口的run方法,是没有返回值的,如果我们现在有一个场景要使用多线程,并且需要有返回值怎么办?
此时,我们就引出有返回值的线程接口,Callable!
Callable: 返回线程执行的结果并且可能抛出异常的线程类!
这么说可能比较抽象,我们使用代码示例,就可以一下子就看明白了!
public class CallDemo implements Callable {//泛型类@Override
public Integer call() throws Exception { //泛型类为返回值
return null;
}}
现在我们看到这个代码示例就应该瞬间明白了,传入泛型类,那么call方法的返回值也会和泛型类。
好了,现在我们拥有callable接口了,但是如何使用呢?难道和Runnable接口一样,也是传入Thread()类吗?
我们从jdk8翻阅一下api字典 java api,发现并没有callable接口的传入参数,难道这是java的失误吗?
文章图片
我们使用适配器模式的思想,如果有个类,同时可以将Runnable接口和Callable接口进行整合,是不是就满足我们这个需求了呢?
没错,是有这种类,它就是FutureTask类!能够提供返回值的异步计算!
2.FutureTask类简介
FutureTask,一个可获得返回值的异步计算类!可以调用方法去开始和取消一个计算,可以查询计算是否完成并且获取计算结果,只有当计算完成时才能获取到计算结果,否则就会阻塞!
3.Callable接口使用
可能看了上述讲解,我们还是不知道如何使用,接下来我们直接用一个Demo来进行示例:
我们先设定一个类,经过三秒中之后返回一个数值,代表计算过程。
public class CallableDemo implements Callable {//和runnable的接口比起来,这是有返回值的接口
//还可以抛异常
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName() + "****进入callable了!");
Thread.sleep(3000);
return 1024;
}
}
接下来我们将用FutureTask获取这个运算结果:
//把实现callable的接口当做参数传入futuretask
FutureTask futureTask = new FutureTask<>(new CallableDemo());
//因为futureTask实现了Runnable接口,像普通的Runnable实现类一样传入Thread就可以了
Thread t1 = new Thread(futureTask, "t1");
//正常启动
t1.start();
//尝试获取返回结果
System.out.println("****** result=" + futureTask.get());
最终计算结果:
文章图片
根据注释,Future可以很容易地就被使用了。
但是如果我们修改一下代码呢?
//把实现callable的接口当做参数传入futuretask
FutureTask futureTask = new FutureTask<>(new CallableDemo());
//因为futureTask实现了Runnable接口,像普通的Runnable实现类一样传入Thread就可以了
Thread t1 = new Thread(futureTask, "t1");
//让两个相同的线程同时执行futureTask
Thread t2 = new Thread(futureTask, "t2");
//正常启动
t1.start();
t2.start();
//尝试获取返回结果
System.out.println("****** result=" + futureTask.get());
运行结果为:
文章图片
看,还是和刚才一样,也就是说一个FutureTask只能绑定一个Thread!绑定多了也是无效的!
总结:
Callable是一种可以拥有返回值的线程类。
优点:
可以获得任务执行返回值;
通过与Future的结合,可以实现利用Future来跟踪异步计算的结果。
推荐阅读
- 线程多对多交替打印-condition
- 启动多个线程并按顺序执行
- java|使用线程Thread和Runnable输出1到100之间的偶数
- java多线程轮流打印数据问题
- Java|面试必问!Java 多线程中两个线程交替执行,一个输出偶数,一个输出奇数
- 【Java多线程实战设计】用三个线程按顺序循环打印abc三个字母,比如abcabcabc
- java多线程(循环输出ABC)
- 多线程(至少三个线程)分别打印A、B、C,要求按ABC的顺序循环打印10次。