并发编程基础-Callable接口
# Callable接口
# 1. Callable概述
# 1.1 创建线程的四种方法:
通过创建
Thread
类。通过使用
Runnable
创建线程。通过
Callable
接口创建线程。通过
线程池
创建线程
# 1.2 Callable (opens new window)接口和Runnable (opens new window)接口比较
Callable (opens new window) java.util.concurrent
**Runnable ** (opens new window) java.lang
实现方法名称不同:Callable通过call方法实现;Runable通过run方法实现。
是否有返回值:Runnable 缺少的一项功能是,当线程终止时【即run方法完成时】,我们无法使线程返回结果。为了支持此功能,Java 中提供了 Callable 接口。
是否抛出异常:call方法可以引发异常,而run则不能。
不能直接替换
Runnable
,因为 Thread 类的构造方法根本没有 Callable。点击查看
线程Thread
java.lang
构造方法
# 1.3 Callable实现 😈
因为Callable没有在Thread类的构造方法里,不能直接在Thread中直接使用,如下:
//实现Callable接口
class MyThread2 implements Callable {
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName()+" come in callable");
return 200;
}
}
//Callable接口,报错
new Thread(new MyThread2(),"BB").start();
2
3
4
5
6
7
8
9
10
11
12
提示
怎样在Runable和Callable两个接口中建立联系?
Runnable接口有实现类FutureTask(java.util.concurrent
), FutureTask构造方法可以传递Callable
FutureTask代码实现
// 实现Callable接口
class MyThread2 implements Callable {
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName()+" come in callable");
return 200;
}
}
// FutureTask
FutureTask<Integer> futureTask1 = new FutureTask<>(new MyThread2());
// lambad表达式简化
FutureTask<Integer> futureTask2 = new FutureTask<>(()->{
System.out.println(Thread.currentThread().getName()+" come in callable");
return 1024;
});
//创建一个线程
new Thread(futureTask2,"lucy").start();
new Thread(futureTask1,"mary").start();
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 2. FutureTask (opens new window)
FutureTask:未来任务
在主线程中需要执行比较耗时的操作时,但又不想阻塞主线程时,可以把这些作业交给 Future 对象在后台完成。
当主线程将来需要时,就可以通过 Future 对象获得后台作业的计算结果或者执行状态
一般 FutureTask 多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。
仅在计算完成时才能检索结果;如果计算尚未完成,则阻塞 get 方法
一旦计算完成,就不能再重新开始或取消计算
get 方法而获取结果只有在计算完成时获取,否则会一直阻塞直到任务转入完成状态,然后会返回结果或者抛出异常
get 只计算一次,因此 get 方法放到最后