JDK源码解析---Thread

1.概述

Java所有多线程的实现,均通过封装Thread类实现

2.类图

在这里插入图片描述

实现了Runnable接口

Runnable的源码非常简单,只有一个抽象方法。@FunctionalInterface是jdk1.8出现的函数式接口。用于Lamda表达式。

可以把Runnable看作是一个任务,run方法就是任务要完成的事情

3.属性

private volatile char  name[];//线程的名字
private int            priority;//线程的优先级
private Thread         threadQ;
private long           eetop;

private boolean     single_step;// 是否单步执行此线程

private boolean     daemon = false;//是否是守护线程,默认不是守护线程

private boolean     stillborn = false;//JVM状态

private Runnable target;//需要完成的任务

private ThreadGroup group;//线程组

private ClassLoader contextClassLoader;//此线程的上下文类加载器

private AccessControlContext inheritedAccessControlContext;//此线程的继承的访问控制上下文

private static int threadInitNumber;//用于自动编号

ThreadLocal.ThreadLocalMap threadLocals = null;//

ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;//

private long stackSize;//线程请求的堆栈大小。

private long nativeParkEventPointer;

private long tid;//线程ID

private static long threadSeqNumber;//用于生成线程ID

private volatile int threadStatus = 0;//线程的状态

volatile Object parkBlocker;//

private volatile Interruptible blocker;//在可中断的I / O操作中阻塞该线程的对象(如果有)。设置此线程的中断状态后,应调用阻塞程序的中断方法

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

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

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

4.构造方法

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,
              long stackSize) {
    init(group, target, name, stackSize);
}

上述构造方法都调用了init来实现 init是一个private方法只有Thread内部自己使用

private void init(ThreadGroup g, Runnable target, String name,
                  long stackSize) {
    init(g, target, name, stackSize, null);
}
//参数分别表示 线程组,任务,线程名字,堆栈大小,此线程的继承的访问控制上下文
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();//获取当前执行的线程
        SecurityManager security = System.getSecurityManager();//获取安全管理器
        if (g == null) {//线程组为空
            if (security != null) {//若安全管理器不为空
                g = security.getThreadGroup();//用安全管理器来获取线程组
            }
            if (g == null) {//若为空
                g = parent.getThreadGroup();//则使用parent来获取线程组。
            }
        }

        g.checkAccess();

        /*
         * Do we have the required permissions?
         检查是否有权限
         */
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }

        g.addUnstarted();//增加线程组中未启动的线程的数量。

        this.group = g;//设置线程组
        this.daemon = parent.isDaemon();//当前线程的守护线程标记等于parent线程的守护线程标记。说明父线程是守护线程的话,子线程也必须是守护线程
        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);

        tid = nextThreadID();//线程id
    }

5.本地方法

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

public static native void yield();//给调度程序的提示是当前线程愿意放弃对处理器的当前使用。

public static native void sleep(long millis)//使线程休眠一定时间,不释放锁

private native void start0()//启动线程

private native boolean isInterrupted(boolean ClearInterrupted);//是否被中断,根据传入的参数,来重置或者不重置中断标记

public final native boolean isAlive();//当前线程是否存活

@Deprecated
public native int countStackFrames();//统计栈帧数量

public static native boolean holdsLock(Object obj);//是否持有锁

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);//设置名字

6.常用方法

  1. sleep(long millis, int nanos)

    纳秒的作用仅仅只是在millis的基础上加一毫秒。

public static void sleep(long millis, int nanos)
throws InterruptedException {
    if (millis < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }

    if (nanos < 0 || nanos > 999999) {
        throw new IllegalArgumentException(
                            "nanosecond timeout value out of range");
    }

    if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
        millis++;
    }

    sleep(millis);
}
  1. start()
public synchronized void start() {
    if (threadStatus != 0)
        throw new IllegalThreadStateException();
    group.add(this);//将该线程添加到线程组中

    boolean started = false;
    try {
        start0();//真正的执行启动线程是由本地方法来实现的
        started = true;//启动成功将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 */
        }
    }
}
void threadStartFailed(Thread t) {
    synchronized(this) {
        remove(t);
        nUnstartedThreads++;
    }
}
  1. run

    去实现了runnable接口中的run方法

public void run() {
    if (target != null) {
        target.run();
    }
}
  1. exit

    用于退出线程前清空成员变量。以及线程组中移除该线程。

private void exit() {
    if (group != null) {
        group.threadTerminated(this);
        group = null;
    }
    /* Aggressively null out all reference fields: see bug 4006245 */
    target = null;
    /* Speed the release of some of these resources */
    threadLocals = null;
    inheritableThreadLocals = null;
    inheritedAccessControlContext = null;
    blocker = null;
    uncaughtExceptionHandler = null;
}
  1. 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();
}

public static boolean interrupted() {//判断是否处于中断,并重置中断标记
    return currentThread().isInterrupted(true);
}

public boolean isInterrupted() {//判断是否处于中断,不重置中断标记
    return isInterrupted(false);
}
  1. setPriority(int newPriority) 设置优先级
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);
    }
}
  1. join 其实内部调用的是Object的wait方法
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);//若线程存活等待delay时间
            now = System.currentTimeMillis() - base;
        }
    }
}

//感觉也没什么用,纳秒的作用仅仅在毫米的基础上加一毫秒
public final synchronized void join(long millis, int nanos)
    throws InterruptedException {
    if (millis < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }
    if (nanos < 0 || nanos > 999999) {
        throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
    }
    if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
        millis++;
    }
    join(millis);
}

  1. setDaemon(boolean on) 设置守护线程标识
public final void setDaemon(boolean on) {
    checkAccess();
    if (isAlive()) {
        throw new IllegalThreadStateException();
    }
    daemon = on;
}

7.线程状态

java中线程的状态有6种

public enum State {

    NEW,

    RUNNABLE,

    BLOCKED,

    WAITING,

    TIMED_WAITING,

    TERMINATED;
}

刚创建的线程 还没有start之前的状态是NEW

就绪状态(可运行线程的线程状态。 处于可运行状态的线程正在Java虚拟机中执行,但它可能正在等待来自操作系统(例如处理器)的其他资源)的线程是RUNNABLE

没有获得临界资源被阻塞的线程是BLOCKED

无限期等待状态 调用了Object.wait,Thread.join,LockSupport.park的线程是WAITING

有限等待状态 调用了Thread.sleep Object.wait带参数 Thread.join带参数 LockSupport.parkNanos LockSupport.parkUntil 的线程是TIMED_WAITING

终止了的线程是TERMINATED

猜你喜欢

转载自blog.csdn.net/gongsenlin341/article/details/107782323