要创建一个线程,可以继承自 Thread 类,或者实现 Runnable 接口,但 JUC 还提供了另外一种方式,通过 Callable + FutureTask 创建并使用线程。
Future 是 JDK 提供用于处理多线程环境异步问题的一种模式,而 FutrueTask 就是对 Future 模式的一种实现。下面通过一段对话来理解什么是“Futura 模式”。
老板:“小王,把会议纪要整理好给我。”
小王:“好的,没问题。”
随后,小王立刻开始整理,几分钟后,小王整理好的文件发送给老板。
以上场景,在多线程之中称为“Futura 模式”。当客户端(老板)向服务端(小王)发起一个请求时,服务端会立刻给客户端返回一个结果(好的,没问题。”),但实际任务并没有开始执行。客户端在拿到“假的”响应结果的同时,服务端才会去真正执行任务,并在任务处理完毕后,将真正的结果再返回给客户端(整理好的文件发送给老板。)。
Future 模式的处理流程如下:
Future 模式的最大好处就是客户端在发送出请求后,可以马上得到一个结果(假的结果),而不用一直等待着服务端来处理。
在使用 FutureTask 时,get() 方法就用于返回服务端真正处理后的真实值(RealData)。由于服务端不一定马上能处理完毕,因此在调用 get() 方法时会出现一定时间的阻塞(等待服务端处理完毕)。
Callable 和 Runnable 类似,都是创建线程的上级接口。二者的区别是,在用 Runnable 方式创建线程时,需要重写 run() 方法;而用 Callable 方式创建线程时,需要重写 call() 方法。更重要的是,run() 方法没有返回值,但 call() 方法却有一个类型为泛型的返回值(即 call() 方法的返回值可以是任意类型),而且 FutureTask 的 get() 方法来接收此返回值。此外,get() 方法也是一个闭锁式的阻塞方法,该方法会一直等待,直到 call() 方法执行完毕并且 return 返回值为止。需要注意的是 call() 方法和 run() 方法一样,也是通过 start() 来调用的。
使用 Callable 创建线程计算 1 到 100 的和并返回给 Main 线程的 sum 变量。
package concurrent;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class TestCallable {
public static void main(String[] args) {
// 创建一个 Callable 类型的线程对象
MyCallableThread myThread = new MyCallableThread();
// 将线程对象包装成 FutureTask 对象,用于接收线程的返回值
FutureTask<Integer> result = new FutureTask<>(myThread);
// 运行线程
new Thread(result).start();
// 通过 FutureTask 的 get() 接收 myThread 的返回值
try {
Integer sum = result.get();// 以闭锁的方式,获取线程的返回值
System.out.println(sum);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
class MyCallableThread implements Callable<Integer> {
@Override
public Integer call() {
System.out.println("线程运行中...计算1-100之和");
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
return sum;
}
}
线程运行中...计算1-100之和
5050
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/chengqiuming/article/details/123669900
内容来源于网络,如有侵权,请联系作者删除!