① 继承Thread类
/**
* 不推荐的方式
* 将要并行运行的任务与运行机制解耦合,用线程池解决
*/
class ExtendsMethod extends Thread {
@Override
public void run() {
System.out.println("呵呵");
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new ExtendsMethod());
// 不要调用run方法(只会执行同一个线程中的任务) 应调用start
thread.start();
}
}
② 实现Runnable接口
public class ImplRunnable implements Runnable {
@Override
public void run() {
System.out.println("哈哈");
}
public static void main(String[] args) {
Thread thread = new Thread(new ImplRunnable());
thread.start();
}
}
③ 实现Callable接口
Callable与Runnable的区别:run does not return a result and cannot throw a checked execption
public class ImplCallable implements Callable {
// 重写call方法,该方法有返回值,有抛出异常
@Override
public Integer call() throws Exception {
Thread.sleep(2000);
return new Random().nextInt(10);
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 缺点:创建对象方式繁琐
// 创建线程对象
ImplCallable ic = new ImplCallable();
// 启动线程
FutureTask ft = new FutureTask<>(ic);
Thread thread = new Thread(ft);
thread.start();
// 返回值自己获取(抛出异常)
Integer i = ft.get();
System.out.println(i);
}
}
以下是实现③的实现过程:
底层:执行的时候state会从下面的几个变化,正常是0到1到2变化
FutureTask(implements RunnableFuture)源码:
private volatile int state; // 状态,正常状态是0 --> 1 --> 2 变化
private static final int NEW = 0; // 调用构造器
private static final int COMPLETING = 1; // 任务将要执行
private static final int NORMAL = 2; // 任务正常执行结束
private static final int EXCEPTIONAL = 3; // 异常
private static final int CANCELLED = 4; // 线程取消
private static final int INTERRUPTING = 5; // 线程即将被中断
private static final int INTERRUPTED = 6; // 中断线程
callable:任务
outcome:接收方法的返回值,下文提到
(1)首先,调用构造器,传入Callable实现类
此时的状态为state = NEW == 0;
(2)其次,当任务被提交到线程池后,会执行futureTask的run()方法,详情看 FutureTask执行过程
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; ** 这边为传入的Integer即Random().nextInt(10)
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result); ** 如果成功,调用set(产生的随机数)
}
} 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);
}
}
来到set,将传入的result赋值给outcome(上面提到,call方法的返回值),此时state = COMPLETING == 1(将要执行)
/**
* Sets the result of this future to the given value unless
* this future has already been set or has been cancelled.
*
* This method is invoked internally by the {@link #run} method
* upon successful completion of the computation.
*
* @param v the value
*/
protected void set(V v) {
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = v;
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
finishCompletion();
}
}
此时,如果程序正常执行,state很快会变成NORMAL(2),若Runnable中call方法出现异常,则state会变成EXCEPTIONAL,详情请看 FutureTask执行过程
(3)最后,当我们调用get方法获取返回值,查看get方法
public V get() throws InterruptedException, ExecutionException {
int s = state; // 当state <= COMPLETING == 1 时,执行awaitDone
if (s <= COMPLETING)
s = awaitDone(false, 0L);
return report(s); // 当state > 1 时,执行reports
}
其中:awaitDone方法,进入循环,直到state > 1
reports方法:
private V report(int s) throws ExecutionException {
Object x = outcome;
if (s == NORMAL) // 当state == NORMAL == 2 时,返回结果outcome
return (V)x;
if (s >= CANCELLED)
throw new CancellationException();
throw new ExecutionException((Throwable)x);
}
③的结论:get取值,阻塞是在 1 ---> 2之间,什么时候state == 2 ,什么时候返回给get