盘一盘 Thread源码

线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

 

继承关系图

线程的创建方式有很多种。常用的有:继承Thread(),重写该类的run()方法;实现Runnable接口,并重写该接口的run()方法。

其实Thread类本身也是实现了Runnable接口,而run()方法最先是在Runnable接口中定义的方法。

 

主要属性

//  线程的名称
private volatile char  name[];

//  线程的优先级
private int            priority;

//  是否是单步执行
private boolean     single_step;

//  是否是守护线程
private boolean     daemon = false;

//  JVM虚拟机的状态
private boolean     stillborn = false;

//  将会被执行的 Runnable
private Runnable target;

//  当前线程的组
private ThreadGroup group;

// 当前线程的上下文
private ClassLoader contextClassLoader;

// 当前线程继承的访问控制权限
private AccessControlContext inheritedAccessControlContext;

// 默认线程的自动编号
private static int threadInitNumber;
// 得到下个thread ID
private static synchronized int nextThreadNum() {
     return threadInitNumber++;
}

// 与当前线程有关的ThreadLocal值
ThreadLocal.ThreadLocalMap threadLocals = null;

//  与当前线程相关的InheritableThreadLocal值。
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;


//  该线程请求的堆栈大小 默认一般为空 JVM自行分配
private long stackSize;


//  当前线程终止后,JVM的私有状态
private long nativeParkEventPointer;

// 当前线程的专属ID
private long tid;

//  用来生成 thread ID
private static long threadSeqNumber;

//  线程状态,0代表线程未启动 Runable
private volatile int threadStatus = 0;

// 中断阻塞器:当线程发生IO中断时,需要在线程被设置为中断状态后调用该对象的interrupt方法
volatile Object parkBlocker;


// 阻塞器锁,主要用于线程中断
private volatile Interruptible blocker;
private final Object blockerLock = new Object();

// 阻断锁
void blockedOn(Interruptible b) {
     synchronized (blockerLock) {
         blocker = b;
     }
}

//   线程优先级 最低优先级
public final static int MIN_PRIORITY = 1;

// 线程优先级 默认优先级
public final static int NORM_PRIORITY = 5;

// 线程优先级 最高优先级
public final static int MAX_PRIORITY = 10;

 

构造方法

我们平时惯用new Thread()方法去创建一个线程,实际上线程初始化的过程中已经完成了很多默认的配置
//  init方法相关参数
//  g          线程组
//  target     实现 Runnable接口类对象,就是调用 run方法的目标对象
// name       线程名称
// stackSize  栈的大小 该值对JVM而言只是一个建议,JVM会动态选择更合适的值
// acc        访问控制权限
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();

    // 获取系统的security
    SecurityManager security = System.getSecurityManager();

    // 没有指定线程组的话,创建的所有线程属于相同的线程组。
    if (g == null) {
        // 先将secuity的线程组赋给新线程的线程组
        if (security != null) {
            g = security.getThreadGroup();
        }
        
        // 如果还是为空,则设为父线程的线程组
        if (g == null) {
            g = parent.getThreadGroup();
        }
    }
    // 检查当前线程是否有修改权限
    g.checkAccess();

       //  授权
    if (security != null) {
        if (isCCLOverridden(getClass())) {
            security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
        }
    }
    g.addUnstarted();

    // 设置守护线程、优先等级
    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;
    setPriority(priority);
    if (parent.inheritableThreadLocals != null)
        this.inheritableThreadLocals =
            ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
   
    // 分配线程栈的大小
    this.stackSize = stackSize;

    // 分配线程Id ThreadID是由JVM分配的,并不是系统的真正线程ID
    tid = nextThreadID();
}

private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
    init(g, target, name, stackSize, null);
}

public Thread() {
    init(null, null, "Thread-" + nextThreadNum(), 0);
}

public Thread(Runnable target) {
    init(null, target, "Thread-" + nextThreadNum(), 0);
}

Thread(Runnable target, AccessControlContext acc) {
    init(null, target, "Thread-" + nextThreadNum(), 0, acc);
}

public Thread(ThreadGroup group, Runnable target) {
    init(group, target, "Thread-" + nextThreadNum(), 0);
}

public Thread(String name) {
    init(null, null, name, 0);
}

public Thread(ThreadGroup group, String name) {
    init(group, null, name, 0);
}

public Thread(Runnable target, String name) {
    init(null, target, name, 0);
}

public Thread(ThreadGroup group, Runnable target, String name) {
    init(group, target, name, 0);
}

public Thread(ThreadGroup group, Runnable target, String name,
              long stackSize) {
    init(group, target, name, stackSize);
}

 

native方法

// 获得当前线程
public static native Thread currentThread();

// 使当前线程从 运行状态Running 变为 就绪状态 Runnable
public static native void yield();

// 使当前线程进入休眠状态
public static native void sleep(long millis) throws InterruptedException;

// 使线程进入就绪状态 Runnable
private native void start0();

// 判断线程是否为中断状态
private native boolean isInterrupted(boolean ClearInterrupted);

// 判断线程是否存活
public final native boolean isAlive();

// 获取所有线程列表
private native static StackTraceElement[][] dumpThreads(Thread[] threads);
private native static Thread[] getThreads();

// 设置线程优先等级
private native void setPriority0(int newPriority);  

// 停止线程 该方法已被弃用
private native void stop0(Object o);

// 线程暂停
private native void suspend0();

// 线程继续执行
private native void resume0();

// 线程中断
private native void interrupt0();

// 设置线程名
private native void setNativeName(String name);

 

这里不得不说和线程相关的几个Object Native方法。

// 随机唤醒在此对象监视器(锁)上等待的单个线程。
public final native void notify();

//  唤醒所有等待在该对象上的线程。
public final native void notifyAll();

//  导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法
public final void wait() throws InterruptedException {
    wait(0);
}

// 超时等待一段时间,这里的参数是毫秒,也就是等待长达n毫秒,如果没有通知就超时返回。
public final native void wait(long timeout) throws InterruptedException;
我最开始有些疑惑,为什么wait(),notify(),notifyAll()用来操作线程会定义在Object类中?
不妨我们先做一个假设:将wait、notify和线程队列都放到Thread中,那么在wait、notify的调度过程中必然要求某个Thread知道其他所有Thread的信息,显然是不合理的。
而放到对象中,让对象维护所有竞争锁线程的队列,各个线程无必然联系。
 

关键方法

start() 启动线程

public synchronized void start() {
        // 判断线程状态是否启动,不允许同一线程启动2次!
    if (threadStatus != 0)
        throw new IllegalThreadStateException();

    // 向线程组中添加当前线程
    group.add(this);

    // 使线程进入就绪状态 Runnable
    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 */
        }
    }
}

 

checkAccess() 检查当前线程是否有修改权限,该方法在线程状态变更前多次被调用

public final void checkAccess() {
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        // 通过Java安全管理器检查当前线程是否有修改权限
        security.checkAccess(this);
    }
}

 

run()  使线程从就绪状态 Runnable转化为运行状态 Running   -todo线程启动过程中由start到run的过程非常复杂。

public void run() {
    // 调用 run方法的目标对象
    if (target != null) {
        target.run();
    }
}

 

exit()  该方法 run方法执行完成后调用,在线程结束退出之前进行清理工作。

private void exit() {
    // 释放资源
    if (group != null) {
        group.threadTerminated(this);
        group = null;
    }
    
    target = null;
    
    threadLocals = null;
    inheritableThreadLocals = null;
    inheritedAccessControlContext = null;
    blocker = null;
    uncaughtExceptionHandler = null;
}

 

stop() stop方法是不安全的,它会立即停止线程执行,线程的后续执行不连贯。可能会导致一些清理性的工作的得不到完成,如文件,数据库等的关闭。故被标记为@Deprecated
@Deprecated
public final void stop() {
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        checkAccess();
        if (this != Thread.currentThread()) {
            security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
        }
    }
 
    if (threadStatus != 0) {
        resume(); // Wake up thread if it was suspended; no-op otherwise
    }
 
    stop0(new ThreadDeath());
}

 

interrupt()  中断线程

public void interrupt() {
    if (this != Thread.currentThread())
        checkAccess();


    synchronized (blockerLock) {
        Interruptible b = blocker;
        if (b != null) {
            interrupt0();           // Just to set the interrupt flag
            b.interrupt(this);
            return;
        }
    }
    interrupt0();
}

 

setPriority()、getPriority()  设置、获取线程优先级
public final void setPriority(int newPriority) {
    ThreadGroup g;
    checkAccess();
    // 线程优先级范围仅分 1~10 级
    if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
        throw new IllegalArgumentException();
    }
    if((g = getThreadGroup()) != null) {
        if (newPriority > g.getMaxPriority()) {
            newPriority = g.getMaxPriority();
        }
        setPriority0(priority = newPriority);
    }
}

public final int getPriority() {
    return priority;
}

 

 
join()  在当前线程中调用另一个线程的join()方法,使当前线程转入阻塞状态,直到另一个进程运行结束,当前线程再由阻塞转为就绪状态。
public final void join() throws InterruptedException {
    join(0);
}

public final synchronized void join(long millis) throws InterruptedException {
    long base = System.currentTimeMillis();
    long now = 0;


    if (millis < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }


    if (millis == 0) {
        while (isAlive()) {
            wait(0);
        }
    } else {
        while (isAlive()) {
            long delay = millis - now;
            if (delay <= 0) {
                break;
            }
            wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
}

 

setDaemon() 将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。

public final void setDaemon(boolean on) {
    checkAccess();
    // 该方法必须在启动线程前调用
    if (isAlive()) {
        throw new IllegalThreadStateException();
    }
    daemon = on;
}
posted @ 2019-07-20 21:39  柠檬五个半  阅读(599)  评论(0编辑  收藏  举报