创建多线程的第三种方式是使用Callable接口:
- 实现Callable接口
- 创建FutureTask实例
- 创建Thread实例
class MyThread implements Callable{ @Override public String call() throws Exception { System.out.println("call"); TimeUnit.SECONDS.sleep(5); return "success";//有缓存 }
public class JUCDemo30 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyThread myThread = new MyThread();
FutureTask futureTask = new FutureTask(myThread);
Thread thread1 = new Thread(futureTask, "A");
thread1.start();
Thread thread2 = new Thread(futureTask, "B");
thread2.start();
System.out.println(futureTask.get());//阻塞方法
}
}
特点:
- 有返回值,返回值算不出来可抛出异常
- get方法默认阻塞,有缓存
Runnable和Callable both are designed for classes whose instances are potentially executed by another thread。Runnable和Callable实例都被Thread隐式执行。
@FunctionalInterface public interface Callable{ V call() throws Exception; }
Thread代理了FutureTask的run方法,用的是静态代理模式。
Thread是代理角色,FutureTask是真实角色,Runnable是接口。
Thread创建线程,只能与Runnable有联系,与Callable没有关系。
Thread怎么创建Callable线程呢?
在FutureTask类的构造器中找到了Callable,于是我们就可以利用FutureTask来与Callable建立关系。
这里用到了适配器模式:适配器是FutureTask,实现的接口是Runnable,被适配类是实现了Callable接口的实例。FutureTask组合了Callable实例,调用了call方法。
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}



