多线程源码--Thread源码

Posted fondwang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程源码--Thread源码相关的知识,希望对你有一定的参考价值。

前言

  Java.lang.Thread是Java应用程序员对Java多线程的第一站,Thread就是对Java线程本身的抽象

  所以在Java中的线程编程概念中,一个Thread实例 == 一个线程
  线程有哪些属性、行为,Thread大致就有哪些属性、行为。

源码

构造器

  技术图片

public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0); }
public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); }
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); }
Thread(Runnable target, AccessControlContext acc) { init(null, target, "Thread-" + nextThreadNum(), 0, acc, false); }

从上面可以看出,所有的构造器都依赖着init方法

  private void init(ThreadGroup g, Runnable target, String name,long stackSize)

除了上面列表的最后一个构造器外,其他构造器传递的参数,都在上面 init() 方法参数只能。这几个参数的解释如下:

ThreadGroup 线程组;

Runnable 封装线程任务;

String name 线程名称;

long stackSize 虚拟机栈的空间大小,默认为0,不设置 即忽略它。

现在来说说与构造器相关的 init() 方法源码

 技术图片

由上图可见,大多数构造器(就是除上面最后一个),都是先将数据传递上图第一个init方法,然后内部再次调用它的重载方法。我们来看看这个方法源码

private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc,
                      boolean inheritThreadLocals) {
        if (name == null) { //线程名称为空抛出异常,构造器不传入线程名称时,会使用默认的。
            throw new NullPointerException("name cannot be null");
        }
        this.name = name; //名称赋值
        Thread parent = currentThread(); //父线程,currentThread()是个本地方法,意思是这个线程的父线程是正在运行的线程,也就是创建这个线程的线程
        SecurityManager security = System.getSecurityManager(); //安全管理器
        if (g == null) {  //如果线程组为空
            //如果安全管理器不为空,则当前线程组就使用管理器指定的线程组
            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 (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        //保存指定的堆栈大小
        this.stackSize = stackSize;

        //设置线程ID
        tid = nextThreadID();
    }

属性

    private volatile String name; //线程名称
    private int            priority; //线程优先级
    private Thread         threadQ; 
    private long           eetop; 
    //是否单步执行这个线程。
    private boolean     single_step;
    //是否为守护线程
    private boolean     daemon = false;
    //jvm状态值
    private boolean     stillborn = false;
    //线程任务
    private Runnable target;
    //线程组
    private ThreadGroup group;
    //此线程的上下文类装入器
    private ClassLoader contextClassLoader;
    //它封装的上下文做出系统资源访问决策。
    private AccessControlContext inheritedAccessControlContext;

    //自动编号。就是当没有设置线程名称的时候。我们看到的Thread-0 Thread-1
    private static int threadInitNumber;
    private long stackSize; //线程堆栈空间大小,默认0,不用管

    //jvm私有状态,在本机线程终止后仍然存在。
    private long nativeParkEventPointer;
    private long tid; //线程ID

    //用于生成线程ID
    private static long threadSeqNumber;
    private volatile int threadStatus = 0;//线程初始状态。表示线程尚未启动
    volatile Object parkBlocker;
    private volatile Interruptible blocker;
    private final Object blockerLock = new Object();//用于synchronized关键字的实例锁
    public final static int MIN_PRIORITY = 1;//最小优先级
    public final static int NORM_PRIORITY = 5;//默认优先级
    public final static int MAX_PRIORITY = 10;//最大优先级

常用的关键方法

start()启动方法

public synchronized void start() {
        //零状态值对应于状态“NEW”。
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        //添加到线程组
        group.add(this);
        boolean started = false;
        try {
            start0();//这个方法是本地方法,意思启动线程
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                //什么也不做。如果start0抛出一个投掷物它将被传递到调用堆栈
            }
        }
    }
private native void start0(); //start0本地方法

run()运行方法

public void run() {
     //线程任务不为空时,调用父接口的run方法
if (target != null) { target.run(); } }

exit()退出方法

//清除必要的资源
private
void exit() { if (group != null) { group.threadTerminated(this); group = null; } target = null; threadLocals = null; inheritableThreadLocals = null; inheritedAccessControlContext = null; blocker = null; uncaughtExceptionHandler = null; }

interrupt()中断方法

public void interrupt() {
        if (this != Thread.currentThread())
            checkAccess();//权限检查
        synchronized (blockerLock) {
            Interruptible b = blocker; //设置中断接口
            if (b != null) {
                interrupt0(); // 设置中断标志
                b.interrupt(this);
                return;
            }
        }
        interrupt0();
    }
//interrupt0()是本地方法

interrupted() 是否已中断

public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }
public boolean isInterrupted() {
        return isInterrupted(false);
    }
private native boolean isInterrupted(boolean ClearInterrupted);

线程是否被激活isAlive()

public final native boolean isAlive();

线程优先级相关方法

//优先级设置
public
final void setPriority(int newPriority) { ThreadGroup g; checkAccess();//权限效验 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; }

线程名称

//名称设置
public final synchronized void setName(String name) { checkAccess(); if (name == null) { //为空,抛出异常 throw new NullPointerException("name cannot be null"); } this.name = name; if (threadStatus != 0) { //线程已启动 setNativeName(name); //调用本地方法设置名称 } }
//返回名称
public final String getName() { return name; }

 


public final ThreadGroup getThreadGroup() { return group; }  //返回线程组

 

public static int activeCount() { return currentThread().getThreadGroup().activeCount(); } //返回线程组活动的线程数

 

public static int enumerate(Thread tarray[]) { return currentThread().getThreadGroup().enumerate(tarray); }  //线程组添加线程集合

 

public static native void yield();  //暂停一下线程,回到就绪状态


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) {  //传递参数小于0,抛异常
            throw new IllegalArgumentException("timeout value is negative");
        }
     //参数为0
if (millis == 0) { while (isAlive()) { //线程处于运行状态 wait(0); //调用Object的wait方法 } } else { //如果参数大于0 while (isAlive()) { long delay = millis - now; if (delay <= 0) { //当前时间不能大于设置的时间之后的时间 break; } wait(delay); //调用Object的wait方法 now = System.currentTimeMillis() - base; //当前时间 } } } public final synchronized void join(long millis, int nanos) throws InterruptedException { if (millis < 0) { //不可小于0 throw new IllegalArgumentException("timeout value is negative"); } if (nanos < 0 || nanos > 999999) { //纳秒不可超过规定范围 throw new IllegalArgumentException( "nanosecond timeout value out of range"); }      //如果纳秒符合条件,秒自增1 if (nanos >= 500000 || (nanos != 0 && millis == 0)) { millis++; } join(millis); //调用上面的方法 }

sleep()方法

public static void sleep(long millis, int nanos) throws InterruptedException {
        if (millis < 0) { //参数必须大于0
            throw new IllegalArgumentException("timeout value is negative");
        }
        if (nanos < 0 || nanos > 999999) { //纳秒要在规定范围
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }
     //如果纳秒符合条件,秒自增1
if (nanos >= 500000 || (nanos != 0 && millis == 0)) { millis++; } sleep(millis); //调用本地方法 }
public static native void sleep(long millis) throws InterruptedException;  //本地方法

Daemon相关方法

public final void setDaemon(boolean on) {  //设置是否为守护线程
        checkAccess(); //权限效验
        if (isAlive()) {  //当前线程不能为激活状态
            throw new IllegalThreadStateException();
        }
        daemon = on;  //设置当前线程是否为守护线程
    }
//是否为守护线程
public final boolean isDaemon() { return daemon; }

 

以上就是常用的api源码,个人能力不足,还请见谅,待之后进行完善。

以上是关于多线程源码--Thread源码的主要内容,如果未能解决你的问题,请参考以下文章

干货:Java多线程详解(内附源码)

多线程-Thread与Runnable源码分析

我的jdk源码:Thread类

java Thread源码分析

多线程 Thread 线程同步 synchronized

thread start()方法源码解析