11 java源码解析-Thread

 其他 源码解析 https://blog.csdn.net/qq_32726809/article/category/8035214 

1类的声明

public
class Thread implements Runnable 
  • 实现了Runnable接口
  • 在程序开发中只要是多线程肯定永远以实现Runnable接口为主。

1.1Runnable 说明

public interface Runnable {
    public abstract void run();
}

只有一个run的方法。

2常用属性

 private volatile String name;  /*线程名*/
 private int            priority; /* 优先级*/

 
  /* Whether or not to single_step this thread. */
    private boolean     single_step;/*是否单步执行*/

    /* Whether or not the thread is a daemon thread. */
    private boolean     daemon = false;/*是否守护线程*/

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

    /* What will be run. */
    private Runnable target;/*将会被执行的runnable*/

    /* The group of this thread */
    private ThreadGroup group;/*线程组*/

    /* The context ClassLoader for this thread *//**/
    private ClassLoader contextClassLoader;

    /* The inherited AccessControlContext of this thread */
    private AccessControlContext inheritedAccessControlContext;

    /* For autonumbering anonymous threads. */
    private static int threadInitNumber;/*线程的自动编号*/
    private static synchronized int nextThreadNum() {/*-----------------------------------------1*/
        return threadInitNumber++;
    }

    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;

    /*
     * InheritableThreadLocal values pertaining to this thread. This map is
     * maintained by the InheritableThreadLocal class.
     */
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

    /*
     * The requested stack size for this thread, or 0 if the creator did
     * not specify a stack size.  It is up to the VM to do whatever it
     * likes with this number; some VMs will ignore it.
     */
    private long stackSize;

    /*
     * JVM-private state that persists after native thread termination.
     */
    private long nativeParkEventPointer;

    /*
     * Thread ID
     */
    private long tid;/*线程id,每个线程都会专属的id*/

    /* For generating thread ID */
    private static long threadSeqNumber;

    /* Java thread status for tools,
     * initialized to indicate thread 'not yet started'
     */

    private volatile int threadStatus = 0;/*线程状态,1.8新加的,默认是启动状态*/


    private static synchronized long nextThreadID() { /*下个线程id*/
        return ++threadSeqNumber;
    }

    /**
     * The argument supplied to the current call to
     * java.util.concurrent.locks.LockSupport.park.
     * Set by (private) java.util.concurrent.locks.LockSupport.setBlocker
     * Accessed using java.util.concurrent.locks.LockSupport.getBlocker
     */
    volatile Object parkBlocker;

    /* The object in which this thread is blocked in an interruptible I/O
     * operation, if any.  The blocker's interrupt method should be invoked
     * after setting this thread's interrupt status.
     */
    private volatile Interruptible blocker;
    private final Object blockerLock = new Object();

    /* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code
     */
    void blockedOn(Interruptible b) {
        synchronized (blockerLock) {
            blocker = b;
        }
    }

    /**
     * The minimum priority that a thread can have.
     */
    public final static int MIN_PRIORITY = 1;/*线程最小优先级*/

   /**
     * The default priority that is assigned to a thread.
     */
    public final static int NORM_PRIORITY = 5;/*默认优先级*/

    /**
     * The maximum priority that a thread can have.
     */
    public final static int MAX_PRIORITY = 10;/*最高优先级*/

    public enum State {
 
        NEW,
        RUNNABLE,
        BLOCKED,
        WAITING,
        TIMED_WAITING,
        TERMINATED;
 
      }

 
  • Runable 个人感觉就像汽车里的货物,而Thread就像汽车
  • 1处这个方法有 synchronized 修饰,是线程安全的
  • 线程六状态:
  • NEW
  • 创建后未分配资源的状态,没有start的线程
  • RUNNABLE
  • 可运行。一旦调用start()方法,线程进入Runnable状态,此时,该线程可能在运行,也可能没有运行。这取决于操作系统给线程提供的运行的时间。
  • 线程被分配完资源后,便进入待准备状态,可运行,等待cpu的执行
  • BLOCKED
  • 被阻塞。当一个线程获取一个内部的对象锁,而这个锁被其他线程持有,则该线程进入阻塞状态。当所有线程释放掉该锁,且线程调度器允许该线程持有这个对象锁时,该线程进入到非阻塞状态。
  • 被同步块阻塞或者io阻塞
  • WAITING
  • 等待,等待被别人唤醒
  • TIMED_WAITING
  • 时间等待,睡够时间了,自己就起来了。
  • TERMINATED
  • 被终止。一般有两种情况:run()方法正常执行完毕而正常死亡。另一种情况是:没有捕获的异常终止了run()方法而意外死亡。
  • 正常执行完毕,或者异常中断

 

3构造函数

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

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

可以看出,线程调用的都是 init(group, target, name, stackSize);方法

3.1init(group, target, name, stackSize)

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

3.2init(ThreadGroup g, Runnable target, String name,long stackSize, AccessControlContext acc,boolean inheritThreadLocals)

  • g 线程组
  • target 要执行的继承Runnable接口的类的对象
  • name 线程的名字
  • stacksize 申请的堆的大小
 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();/*-------------------------1*/
        SecurityManager security = System.getSecurityManager();/*-------------------------2*/
        if (g == null) {
            /* Determine if it's an applet or not */

            /* If there is a security manager, ask the security manager
               what to do. */
            if (security != null) {/*-------------------------3*/
                g = security.getThreadGroup();
            }

            /* If the security doesn't have a strong opinion of the matter
               use the parent thread group. */
            if (g == null) {
                g = parent.getThreadGroup();/*-------------------------4*/
            }
        }

        /* checkAccess regardless of whether or not threadgroup is
           explicitly passed in. */
        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();/*-------------------------5*/
        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);
        /* Stash the specified stack size in case the VM cares */
        this.stackSize = stackSize;

        /* Set thread ID */
        tid = nextThreadID();
    }
  • 1处的意思是后去调用这个线程对象的线程
  • 2处的意思是获取系统的安全管理
  • 此处解释原文如下 if a security manager has already been established for the current application, then that security manager is returned; otherwise, null is returned.
  • 如果系统设置了安全管理器,这里就会返回,如果没有就会返回null
  • 3处的意思是如果安全管理不为空,那么返回适当的线程组
  • 4处的意思是如果安全管理器对线程组没要求,那么返回调用这个线程对象的线程组。

3.3start()

 public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)/*---------------------1*/
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);/*---------------------2*/

        boolean started = false;
        try {
            start0();/*---------------------3*/
            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 */
            }
        }
    }

    private native void start0();
  • 1 处的意思是 如果不是 new 状态 则 不能启动
  • 2 处的意思是 把线程放到线程组中 ,下一篇会详细介绍线程组
  • 3 底层代码实现启动

3.4 run()

public void run() {
        if (target != null) {
            target.run();
        }
    }
  • 如果有Runnable 的对象,就执行 对象Runnable的run操作

3.5 exit()

private void exit() {
        if (group != null) {
            group.threadTerminated(this);/*----------1*/
            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;
    }
 
 
  void threadTerminated(Thread t) {
        synchronized (this) {
            remove(t);

            if (nthreads == 0) {
                notifyAll();
            }
            if (daemon && (nthreads == 0) &&
                (nUnstartedThreads == 0) && (ngroups == 0))
            {
                destroy();
            }
        }
    }
  • 1处的意思是,通知线程组 这个线程已经停止 原文: Notifies the group that the thread t has terminated. Destroy the group if all of the following conditions are true: this is a daemon thread group; there are no more alive or unstarted threads in the group; there are no subgroups in this thread group.
  • 这里需要说是如果线程是守护线程,并且这个线程组中没有存货的线程或者新的线程创建,并且,没有子组在这个线程组里,则删除这个线程组。这是 Threadgroup 中的方法,稍后会对这个做详细解释
  • 这个方法会变量置为空,加快资源释放。
  • 在线程运行完后会调用这个方法,一般是run运行完后

3.6stop()

  • stop这个方法,源码已经过时了,原因是因为,stop方法十分的暴力,会造成一些很难处理的问题。

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

3.8 isAlive();

判断一个线程是否活着。

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

 public final int getPriority() {
        return priority;
    }
    

用来设置优先级

3.10 join(long millis)

阻塞当前线程,(其实了类似于 ajax 中的同步,等请求结束后,才能往下走)这里就是,线程结束后才能往下走

 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);/*----------1*/
                now = System.currentTimeMillis() - base;
            }
        }
    }

  • 1处的意思是等待 delay长的时间, 如果 now <0 则跳出循环

3.11 setDaemon

用来设置守护线程

 public final void setDaemon(boolean on) {
        checkAccess();/*------1*/
        if (isAlive()) {
            throw new IllegalThreadStateException();
        }
        daemon = on;
    }
  • 1处的意思运行的线程是否有权修改这个线程,这个判断来自安全管理器

3.12 toString

返回的线程第一个是名字,第二个是优先级,第三个是组的名字

  public String toString() {
        ThreadGroup group = getThreadGroup();
        if (group != null) {
            return "Thread[" + getName() + "," + getPriority() + "," +
                           group.getName() + "]";
        } else {
            return "Thread[" + getName() + "," + getPriority() + "," +
                            "" + "]";
        }
    }

3.13 getContextClassLoader

  • 获取上下文类加载器
  • 类加载器就是把字节码 加载到 jvm虚拟机中
  • 一个ClassLoader创建时如果没有指定parent,那么它的parent默认就是AppClassLoader。
  public ClassLoader getContextClassLoader() {
        if (contextClassLoader == null)
            return null;
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            ClassLoader.checkClassLoaderPermission(contextClassLoader,
                                                   Reflection.getCallerClass());
        }
        return contextClassLoader;
    }

3.14 getStackTrace()

获取线程的堆栈转储列表

public StackTraceElement[] getStackTrace() {
        if (this != Thread.currentThread()) {
            // check for getStackTrace permission
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkPermission(
                    SecurityConstants.GET_STACK_TRACE_PERMISSION);
            }
            // optimization so we do not call into the vm for threads that
            // have not yet started or have terminated
            if (!isAlive()) {
                return EMPTY_STACK_TRACE;
            }
            StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this});
            StackTraceElement[] stackTrace = stackTraceArray[0];
            // a thread that was alive during the previous isAlive call may have
            // since terminated, therefore not having a stacktrace.
            if (stackTrace == null) {
                stackTrace = EMPTY_STACK_TRACE;
            }
            return stackTrace;
        } else {
            // Don't need JVM help for current thread
            return (new Exception()).getStackTrace();
        }
    }

猜你喜欢

转载自blog.csdn.net/qq_32726809/article/details/82704434