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); } }