目录
1.Thread
1.1start方法源码解析
// 创建一个新的线程
public synchronized void start() {
// 如果没有初始化,抛异常
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
// started 是个标识符,我们在做一些事情的时候,经常这么写
// 动作发生之前标识符是 false,发生完成之后变成 true
boolean started = false;
try {
// 这里会创建一个新的线程,线程状态改变为可执行状态等待分配时间片
start0();
// 这里执行的还是主线程
started = true;
} finally {
try {
// 如果失败,把线程从线程组中删除
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {}
}
}
// 开启新线程使用的是 native 方法
private native void start0();
先将该线程加入到线程组里面,然后才会使用start0方法将线程状态改变为可执行状态等待cpu分配时间片
1.2初始化源码分析
// 无参构造器,线程名字自动生成
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
// g 代表线程组,线程组可以对组内的线程进行批量的操作,比如批量的打断 interrupt
// target 是我们要运行的对象
// name 我们可以自己传,如果不传默认是 "Thread-" + nextThreadNum(),
// stackSize 可以设置堆栈的大小
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name.toCharArray();
// 当前线程作为父线程
Thread parent = currentThread();// 初始化的线程会继承当前线程
this.group = g;// 继承父线程的线程组
this.daemon = parent.isDaemon();// 继承父线程的守护属性
this.priority = parent.getPriority();// 继承父线程的优先级
// 继承父线程的上下文类加载器
// @启动类加载器,@扩展类加载器,@应用程序类加载器,@自定义类加载器
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
// 继承父线程访问控制上下文权限
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
this.target = target;// 设置Runnable接口
setPriority(priority);// 设置优先级
// 继承父线程的inheritableThreadLocals值
if (parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
// 设置栈大小
this.stackSize = stackSize;
// 设置线程id
tid = nextThreadID();
}
初始化线程,先将当前线程作为父线程,然后继承父线程的属性(线程组,守护属性,优先级,类加载器,访问权限,ThreadLocal值),然后设置Runnable接口,设置优先级,设置栈大小,设置线程id
2.Future
2.1基本架构
- 定义了异步计算框架,但是get获取结果是阻塞的;
ps:异步只针对call/run方法的计算任务来说的,获取结果依然是阻塞的
// 如果任务已经成功了,或已经取消了,是无法再取消的,会直接返回取消成功(true)
// 如果任务还没有开始进行时,发起取消,是可以取消成功的。
// 如果取消时,任务已经在运行了,mayInterruptIfRunning 为 true 的话,就可以打断运行中的线程
// mayInterruptIfRunning 为 false,表示不能打断直接返回
boolean cancel(boolean mayInterruptIfRunning);// 取消任务
// 返回线程是否已经被取消了,true 表示已经被取消了
// 如果线程已经运行结束了,isCancelled 和 isDone 返回的都是 true
boolean isCancelled();// 是否已经取消
boolean isDone();// 是否已经运行结束了
// 等待结果返回
// 如果任务被取消了,抛 CancellationException 异常
// 如果等待过程中被打断了,抛 InterruptedException 异常
V get() throws InterruptedException, ExecutionException;
// 等待,但是带有超时时间的,如果超时时间外仍然没有响应,抛 TimeoutException 异常
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
该接口定义了任务取消,等待任务完成,判断是否取消和是否完成方法
3.FutureTask
3.1整体架构
- 实现了RunnableFuture接口适配器(Runnable和Future接口),并且组合了Callable接口
// 任务状态
private volatile int state;
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
private Callable<V> callable;
// 异步线程返回的结果
private Object outcome;
// 当前任务所运行的线程
private volatile Thread runner;
// 记录调用 get 方法时被等待的线程
private volatile WaitNode waiters;
- FutureTask类整合了Runnable、Callable、Future三者的功能
3.2初始化源码解析
// 使用 Callable 进行初始化
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
// 任务状态初始化
this.state = NEW;
}
// 使用 Runnable 初始化,result一般为null 。
public FutureTask(Runnable runnable, V result) {
// 把 runnable 直接适配成了 callable。
this.callable = Executors.callable(runnable, result);
//初始化状态
this.state = NEW;
}
// 转化 Runnable 成 Callable 的适配器类
static final class RunnableAdapter<T> implements Callable<T> {
final Runnable task;
final T result;
RunnableAdapter(Runnable task, T result) {
this.task = task;
this.result = result;
}
public T call() {
task.run();
return result;
}
}
首先可以执行Callable方法,也可以执行Runnable方法
为了统一简化类的复杂性,将Runnable通过适配器模式变为Callable
3.3get源码解析
public V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
if (unit == null)
throw new NullPointerException();
int s = state;
// 如果任务已经在执行中了,并且等待一定的时间后,仍然在执行中,直接抛出异常
if (s <= COMPLETING &&
(s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)
throw new TimeoutException();
// 任务执行成功,返回执行的结果
return report(s);
}