Java线程之Thread、Future、FutureTask源码解析

31 篇文章 0 订阅
16 篇文章 2 订阅

目录

1.Thread

1.1start方法源码解析

1.2初始化源码分析

2.Future

2.1基本架构

3.FutureTask

3.1整体架构

3.2初始化源码解析

3.3get源码解析


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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值