类关系
1、Thread
继承Thread类,并重写run方法
Demo:
class ThreadDemo1 extends Thread {
@Override
public void run() {
log.info("{}", Thread.currentThread().getName());
}
}
线程start后,会调用run方法。 Thread类信息:
class Thread implements Runnable {
//thread 实现了 Runnable 接口
}
2、Runnable和Thread
Thread类的构造函数支持传入Runnable的实现类
Demo:
class RunnableThread implements Runnable {
@Override
public void run() {
log.info("{}", Thread.currentThread().getName());
}
}
private void testRunnableThread() {
Thread t2 = new Thread(new RunnableThread(), "t2");
t2.start();
}
查看源码会发现Thread的构造方法会把Runnable接口的实现类赋值给target
/* What will be run. */
private Runnable target;
//构造方法接受 Runnable 对象
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
//最终runnabel对象会赋值给 target
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
this.target = target;
}
//run 方法默认执行 target的run方法
public void run() {
if (target != null) {
target.run();
}
}
3、Callable和Thread
- Callable和Runnable一样,也是一个函数式接口,二者的区别非常明显,Runnable中run方法没有返回值,Callable中的call方法有返回值(可以通过泛型约束返回值类型)。因此在需要获取线程执行的返回值时,可以使用Callable。
- 在Thread的构造函数中,并没有看到Callable,只有Runnable
- 此时需要一个可以提交Callable给Thread的类,这类就是FutureTask;FutureTask实现类Runnable接口。
总结来说 ,线程执行FutureTask 的run方法 ,run方法内执行 Callable的call方法 ,并把执行结果给到 FutureTask内的 Object outcome; 最终通过 FutureTask 的get方法获取结果
Demo:
class CallableThread implements Callable<Integer> {
@Override
public Integer call() throws Exception {
log.info("{}", Thread.currentThread().getName());
return 1998;
}
}
private FutureTask testCallableThread() throws InterruptedException, ExecutionException {
FutureTask stringFutureTask = new FutureTask<>(new CallableThread());
Thread t3 = new Thread(stringFutureTask, "t3");
t3.start();
//阻塞的获取线程结果
final Object o = stringFutureTask.get();
return stringFutureTask;
}