1、继承Thread实现。
2、实现Runnable接口。
3、实现Callable接口,用FutureTask接收返回值。
总结:其实线程最核心的是Runnable,因为Thread和FutureTask都继承该接口来实现具体功能,即拓展实现。而Thread实现的start0()方法,其调用本地方法开启新线程。
看第三种:
1)其中FutureTask继承了Runnable接口,所以可以当做一个线程来处理,并得到返回值。
2)future.get()的方法实现由必要看一下,当线程未执行或未结束时,会阻塞当前线程,直到该线程执行完毕。
3)为什么可以获得返回值呢?看下future.run()就懂了,对Runnable的run()包装了一层,调用继承Callable的方法获得返回值保存给当前future,详见代码2。
代码1(测试代码):
public static void main(String[] args) throws FileNotFoundException, InterruptedException, ExecutionException {
FutureTask<Integer> future=new FutureTask<Integer>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
Thread.sleep(2000);
return 182;
}
});
System.out.println(future.isDone());
new MyThread(future).start();
new Thread(future).start();
System.out.println(future.get());
}
static class MyThread extends Thread{
FutureTask<Integer> future;
private MyThread(FutureTask<Integer> future) {
this.future = future;
}
@Override
public void run() {
try {
System.out.println("获取到了"+this.future.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出:
false
获取到了182
182
代码2(FutureTask实现方法):
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> 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);
}
}