Callable接口和Runnale接口一样, 也能
创建新线程
Runnable接口和Callable接口的不同:
- 是否有返回值
- 是否抛出异常
- 实现方法不同,一个是run方法,一个是call方法
如何使用
Runnabe接口有一个实现类: FutureTask, 他有一个构造方法, 使用Callable接口作为参数
public class FutureTaskDemo{
public static void main(String[] args){
new Thread(new FutureTask<>(() -> {
System.out.println("执行线程: " + Thread.currentThread().getName());
return 200;
}), "AAA").start();
}
}
理解FutrueTask
一篇关于FutureTask的高质量博客
Future共有三种状态:
- 未启动:当创建一个FutureTask对象,并且run方法执行之前,FutureTask处于未启动状态。
- 已启动:FutureTask对象的run方法启动并执行的过程中,FutureTask处于已启动状态。
- 已完成:FutureTask正常执行结束,或者FutureTask执行被取消(cancel方法),或者FutureTask对象run方法执行抛出异常而导致中断而结束,FutureTask都处于已完成状态。
FutureTask(未来任务)怎么理解: 从线程启动前, 已启动, 已完成, 这三个阶段, FutureTask提供了很多方法用来操作这其中过程的方法, 来决定这个线程未来怎么变化
举一个栗子:
老师上课,口渴了,去买水不合适,讲课这个线程必须继续
- 找班长帮忙买水 (run一个未来任务线程, 会在未来某时刻获得结果)
- 买回来之前是没有水喝的 (启动前get阻塞)
- 买回来之前, 突然发现教室还有水, 马上把班长叫回来 (运行时cancel线程)
- 水买回来后,需要时候可以直接喝 (完成后随时get)
FutureTask的两个基本方法:
- get 获取当前计算结果
- cancel(bool): 取消当前的线程执行, 参数表示该方法是否可以在已启动时阻止
FutureTask的get和cancel方法在不同状态的执行示意图:
举个栗子
最后来一个小demo来理解三个状态:
public class FutureTaskDemo{
private static final FutureTask<Integer> task = new FutureTask<>(() -> {
System.out.println("执行线程: " + Thread.currentThread().getName());
return 200;
});
public static void main(String[] args) throws ExecutionException, InterruptedException{
new Thread(() -> {
while(true){
if(task.isDone()){
try{
System.out.println(task.get());
} catch(InterruptedException | ExecutionException e){
e.printStackTrace();
}
System.out.println("线程已运行结束");
break;
}else {
System.out.println("线程在运行中");
}
}
}).start();
System.out.println("线程还未开始执行");
new Thread(task, "AAA").start();
}
}
|