Future 和 Callable 接口
Future 接口 定义了操作异步任务执行一些方法
比如获取异步任务的执行结果
取消任务的执行
判断任务是否被取消
判断任务执行是否完毕
Callable 接口 中定义了需要有返回的任务需要实现的方法
比如说主线程让一个子线程去执行任务
子线程可能比较耗时
启动子线程开始执行任务后
主线程就去做其他事情了
过了一会才去取消子任务的执行结果
FutureTask 的一个案例
示意图
代码
子线程启动是不会干扰主线程的
主线程会继续执行到结束
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
public class FutureTaskDemo {
// 练习Future 和 Callable 接口
public static void main(String[] args) throws Exception {
FutureTask<Integer> FutureTask = new FutureTask<>(() -> {
// 打印当前线程名
System.out.println(Thread.currentThread().getName()
+"\t"
+"--- come in");
// 线程休眠
try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e){e.printStackTrace();}
return 1024;
});
new Thread(FutureTask,"t1") .start();
System.out.println("继续工作");
System.out.println(FutureTask.get());
}
}
子线程继续执行到结束
把结果返回
FutureTask 的缺点
架构
缺点详解
阻塞
futureTask 的 get 方法建议放在最后
如果放在前面 就是阻塞
阻塞的情况下 只有 get 到线程 t1 里面那个返回值
才能执行下一步操作
这样就不叫并发
并发的要求
克服阻塞 尽量少加锁 替换阻塞
解释
FutureTask.get() 不管是否计算完成 都被阻塞
只要出现 get 方法 都会阻塞
等待结果出来才允许
很坑爹
解决 FutureTask.get() 的阻塞问题
超时保护
传入参数 代表只等待当前线程多久
// 阻塞
// System.out.println(FutureTask.get());
// 只等两秒钟
System.out.println(FutureTask.get(2L,TimeUnit.SECONDS));
System.out.println("继续工作");
超时就会报错
轮询
工作中不要阻塞 高并发
有一种思想叫 CAS
用 轮询 替代 阻塞
不要用阻塞 尽量用轮询替代
轮询也是阻塞
小结
复杂任务
当完成的时候 异步回调 (when complete)
多线程异步任务编排
对 Future 的改进
我们选择到了 CompletableFuture
FutureTask 架构
CompletableFuture 架构
思想
个人理解意思
三个线程可以异步任务调度
合作任务
共同完成一个任务
实现
看书
linux 中的管道分隔符