8、Callable
多线程中 , 三种获得多线程的方式
1、继承Thread类
2、实现Runnable接口
3、实现 Callable接口
Callable与Runnable的区别
//创建新类MyThread实现runnable接口
class MyThread implements Runnable{
@Override
public void run() {
}
}
//新类MyThread2实现callable接口
class MyThread2 implements Callable<Integer>{
@Override
public Integer call() throws Exception {
return 200;
}
}
Callable可以有返回值 可以检查异常 可以细粒度化的对多线程进行控制和管理
实例使用代码
Callable实现方式
Thread不能直接调用Callable的实现类 因为 thread类的构造方法根本没有Callable
但是从中可以分析出 Thread类的构造方法需要实现Runable接口的实现类
通过 java多态的思想,一个类可以实现多个接口!!
class MyThread implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("-----Callable here");
return 200;
}
}
public class CallableDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyThread myThread = new MyThread();
FutureTask futureTask= new FutureTask(myThread);
Thread t1 = new Thread(futureTask);
t1.start();
System.out.println(futureTask.get());
// 结果
// -----Callable here
// 200
}
}
线程再处理一系列问题的时候
如果遇到比较困难的问题 另起一个线程(Callable)去处理这个困难问题
原线程继续解决其他问题
当两个线程的问题都解决完了 再进行汇总 (get方法获取Callable的返回值)
原理上理解FutureTask
1、在主线程中需要执行比较耗时的操作时,但又不想阻塞主线程时,可以把这些作业交给Future对象在后台完成,
当主线程将来需要时,就可以通过Future对象获得后台作业的计算结果或者执行状态。
2、一般FutureTask多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。
3、仅在计算完成时才能检索结果;如果计算尚未完成,则阻塞 get 方法。一旦计算完成,
就不能再重新开始或取消计算。get方法而获取结果只有在计算完成时获取,否则会一直阻塞直到任务转入完成状态,
4、然后会返回结果或者抛出异常。
两个或多个线程进行调用同一个Callable接口的call()方法只计算一次
(可以理解为 比如让Callable接口去计算 1 + 1 计算结果已经知道是2了 在调用一次 就不在进行计算了)
get方法一般放在最后一行