Skip to content
DAILY QUOTE

“ ”

Callable 和 Runable 对比: 比如Callable 是你自己,你想通过你的女朋友 Runable 认识她的闺蜜 Thread

  • Callable 是 java.util 包下 concurrent 下的接口,有返回值,可以抛出被检查的异常
  • Runable 是 java.lang 包下的接口,没有返回值,不可以抛出被检查的异常
  • 二者调用的方法不同,run()/ call()

同样的 Lock 和 Synchronized 二者的区别,前者是java.util 下的接口 后者是 java.lang 下的关键字。

java
new Thread(new Runnable()).start();  //创建一个线程去执行一个没有返回值的任务。
new Thread(new FutureTask<V>()).start(); //FutureTask实现了 RunnableFuture接口,而 RunnableFuture又继承了Runnable。所以 Thread 觉得它是 Runnable,就接收了它。
new Thread(new FutureTask<V>(Callable)).start();

代码测试

java
package com.mystpet.Callable;  
  
import java.util.concurrent.Callable;  
import java.util.concurrent.ExecutionException;  
import java.util.concurrent.FutureTask;  
  
public class CallableTest {  
    public static void main(String[] args) throws ExecutionException, InterruptedException {  
        MyThread thread = new MyThread();  
        FutureTask<Integer> futureTask = new FutureTask<>(thread);  
  
        new Thread(futureTask,"A").start();  
        new Thread(futureTask,"B").start();  
  
        Integer integer=futureTask.get();  
  
        System.out.println(integer);  
  
    }  
}  
class MyThread implements Callable<Integer> {  
  
    @Override  
    public Integer call() throws Exception {  
        System.out.println("call");  
        return 1024;  
    }  
}

运行结果:

A与B共用的是同一个 futureTask 对象

  • 缓存机制FutureTask 内部维护了一个 state(状态机)。

  • 只执行一次:当线程 A 拿到 futureTask 并成功调用了 call() 方法后,FutureTask 会将状态从 NEW 更新为 COMPLETING,最后变为 NORMAL(完成)。

  • 结果复用:当线程 B 启动时,它会检查 futureTask 的状态。发现任务已经执行过或正在执行,它就不会再重复调用 call() 方法,而是直接等待结果。

细节: 1、有缓存

2、结果可能需要等待,会阻塞!