标签:ssi thread sof zed dstar group until run obj
创建线程的几种方式:
1. 通过继承 Thread 类
public static class MyThreadOne extends Thread{
@Override
public void run() {
System.out.println("MyThreadOne running ... ");
}
}
2. 通过实现Runnable接口
public static class MyThreadTwo implements Runnable{
@Override
public void run() {
System.out.println("myThreadTwo running ... ");
}
}
3. 通过Callable接口和FutureTask实现有返回值的线程
public static class MyThreadThree implements Callable<String>{
@Override
public String call() throws Exception {
System.out.println("MyThreadThree running .... ");
return "success";
}
}
具体的线程执行
public static void main(String[] args) {
MyThreadOne myThreadOne = new MyThreadOne();
myThreadOne.start();
Thread thread = new Thread(new MyThreadTwo());
thread.start();
// futureTask 类实现了 RunnableFuture 接口 该接口继承了 Runable 接口 继承runnable 接口 就能通过 new Thread(new Runable())方式
// 通过线程执行 futureTask 中的 run 方法 ; 继承 future 接口 能通过 get 方法 阻塞线程 获取放回直
FutureTask<String> stringFutureTask = new FutureTask<>(new MyThreadThree());
new Thread(stringFutureTask).start();
try {
// get 时通过 LockSupport.park() 阻塞线程
String s = stringFutureTask.get();
System.out.println(s);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
原理探究:
1. 关于第三种方式是如何实现线程执行 实现 Callable 接口中的 call 方法的?
通过debug 一步一步查看执行过程可以发现
thread.start方法创建线程,当线程被CPU分配时间片时, Runable实现类中的 run 方法,因为 FutureTask 类实现了 RunnableFuture 接口 该接口继承了 Runnable 和 Future接口
实际上执行的是FutureTask 中的 run 方法,run 方法中执行 Callable接口中run 方法 也就是 自己实现类中的run 方法;
执行流程:
FutureTask<String> stringFutureTask = new FutureTask<>(new MyThreadThree()); new Thread(stringFutureTask).start();
线程启动:
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group‘s list of threads
* and the group‘s unstarted count can be decremented. */
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
当线程分配CPU 时间后执行 run 方法:
/* What will be run. */
private Runnable target;
public void run() { if (target != null) { target.run(); } }
RunableFuture 继承 Runnable 接口 和 Future 接口 ,而 FutureTask s实现 Runnable接口,执行 FutureTask 中的 run 方法
public class FutureTask<V> implements RunnableFuture<V> {
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 {
// 执行 Callale 实现类中的 call方法
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);
}
}
}
该方法会调用 Callable 的接口的实现类,也就是我们自己的Callable 接口实现类中的call方法
2. get方法是如何获取到 线程的返回值的?
可以发现在执行FutureTask 中的 run 方法中,在执行Callable 的call 放回 会获取到 返回值 放到 FutureTask 的局部变量 outcoome 中,然后在通过 get方法当线程执行完成时,获取该临时变量的值返回;
执行 run 方法,执行完成后执行set 方法
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);
}
}
set方法将方法的返回值放到 全局变量outcome 中
protected void set(V v) {
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = v;
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
finishCompletion();
}
}
当执行get方法时
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
s = awaitDone(false, 0L);
return report(s);
}
当线程执行完成 会执行report 方法 从里面拿到返回值
private V report(int s) throws ExecutionException {
Object x = outcome;
if (s == NORMAL)
return (V)x;
if (s >= CANCELLED)
throw new CancellationException();
throw new ExecutionException((Throwable)x);
}
3. get方法为啥会阻塞线程?
执行get方法时候,会判断线程的状态,若call方法还未执行完成,会执行 awaiter方法,该方法会通过循环判断线程状态,若线程状态被中断,则通过异常放回
若线程执行完成,则结束循环返回,若为其他状态,通过 LockSupport.park()加锁
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
s = awaitDone(false, 0L);
return report(s);
}
执行awaitNode
private int awaitDone(boolean timed, long nanos)
throws InterruptedException {
final long deadline = timed ? System.nanoTime() + nanos : 0L;
WaitNode q = null;
boolean queued = false;
for (;;) {
if (Thread.interrupted()) {
removeWaiter(q);
throw new InterruptedException();
}
int s = state;
if (s > COMPLETING) {
if (q != null)
q.thread = null;
return s;
}
else if (s == COMPLETING) // cannot time out yet
Thread.yield();
else if (q == null)
q = new WaitNode();
else if (!queued)
queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
q.next = waiters, q);
else if (timed) {
nanos = deadline - System.nanoTime();
if (nanos <= 0L) {
removeWaiter(q);
return state;
}
LockSupport.parkNanos(this, nanos);
}
else
LockSupport.park(this);
}
}
万事预则立,不预则废~~~加油
标签:ssi thread sof zed dstar group until run obj
原文地址:https://www.cnblogs.com/sunyangCoder/p/13532556.html