线程相关 之 Thread源码解析【5】

本文详细剖析了Java的Thread类,包括类的基本介绍、关键属性的讲解以及核心方法的源码分析,帮助读者深入理解线程的内部工作机制。
摘要由CSDN通过智能技术生成

类简介:

/**
 * A <i>thread</i> is a thread of execution in a program. The Java
 * Virtual Machine allows an application to have multiple threads of
 * execution running concurrently.
 * <p>
 * 每个线程都有优先级,高优先级比低优先级优先运行。每个线程都可能被标记为守护线程。一个线程创建了一个新的线程,新的线程和创建它的线程,有相同的优先级。
 * 当且仅当创建线程为守护线程,被创建的线程才是守护线程。
 * Demo:
 *	public static void methodsOfThreadClass () throws Exception {
 *		Thread thread = new Thread() {
 *			@Override
 *			public void run() {
 *				super.run();
 *				System.out.println(Thread.currentThread().getPriority()) ;
 *				Thread innerThread = new Thread(){
 *					@Override
 *					public void run() {
 *						super.run();
 *						System.out.println(Thread.currentThread().getPriority()) ;
 *					}
 *				};
 *				innerThread.start();
 *			}
 *			
 *			
 *		};
 *		thread.setPriority(2);
 *		thread.start(); 
 *	} 
 * 
 * 
 * Every thread has a priority. Threads with higher priority are
 * executed in preference to threads with lower priority. Each thread
 * may or may not also be marked as a daemon. When code running in
 * some thread creates a new <code>Thread</code> object, the new
 * thread has its priority initially set equal to the priority of the
 * creating thread, and is a daemon thread if and only if the
 * creating thread is a daemon.
 * <p>
 * 
 * JVM在如下两种情况下,会终止线程的运行:
 * 1、运行时exit()方法被调用,并且安全管理器允许该操作执行
 * 2、所有不是守护线程的线程全部死了,并且调用run方法也有了返回,或者抛出了异常。
 * 
 * When a Java Virtual Machine starts up, there is usually a single
 * non-daemon thread (which typically calls the method named
 * <code>main</code> of some designated class). The Java Virtual
 * Machine continues to execute threads until either of the following
 * occurs:
 * <ul>
 * <li>The <code>exit</code> method of class <code>Runtime</code> has been
 *     called and the security manager has permitted the exit operation
 *     to take place.
 * <li>All threads that are not daemon threads have died, either by
 *     returning from the call to the <code>run</code> method or by
 *     throwing an exception that propagates beyond the <code>run</code>
 *     method.
 * </ul>
 * <p>
 * 
 * 有两个方法可以创建一个新的线程,
 * 一个是声明Thread的子类,应该重写run方法,子类可以分配内存并且启动。
 * 另外一个方法:声明一个实现Runnable的子类,需要实现run方法。 
 * 
 * There are two ways to create a new thread of execution. One is to
 * declare a class to be a subclass of <code>Thread</code>. This
 * subclass should override the <code>run</code> method of class
 * <code>Thread</code>. An instance of the subclass can then be
 * allocated and started. For example, a thread that computes primes
 * larger than a stated value could be written as follows:
 * <hr><blockquote><pre>
 *     class PrimeThread extends Thread {
 *         long minPrime;
 *         PrimeThread(long minPrime) {
 *             this.minPrime = minPrime;
 *         }
 *
 *         public void run() {
 *             // compute primes larger than minPrime
 *             &nbsp;.&nbsp;.&nbsp;.
 *         }
 *     }
 * </pre></blockquote><hr>
 * <p>
 * The following code would then create a thread and start it running:
 * <blockquote><pre>
 *     PrimeThread p = new PrimeThread(143);
 *     p.start();
 * </pre></blockquote>
 * <p>
 * 
 * The other way to create a thread is to declare a class that
 * implements the <code>Runnable</code> interface. That class then
 * implements the <code>run</code> method. An instance of the class can
 * then be allocated, passed as an argument when creating
 * <code>Thread</code>, and started. The same example in this other
 * style looks like the following:
 * <hr><blockquote><pre>
 *     class PrimeRun implements Runnable {
 *         long minPrime;
 *         PrimeRun(long minPrime) {
 *             this.minPrime = minPrime;
 *         }
 *
 *         public void run() {
 *             // compute primes larger than minPrime
 *             &nbsp;.&nbsp;.&nbsp;.
 *         }
 *     }
 * </pre></blockquote><hr>
 * <p>
 * The following code would then create a thread and start it running:
 * <blockquote><pre>
 *     PrimeRun p = new PrimeRun(143);
 *     new Thread(p).start();
 * </pre></blockquote>
 * <p>
 * 
 * 每个线程都有一个表明身份的名字,多个线程名字可以相同。如果线程创建时没有指定名字,会自动分配一个新的名称。
 * 使用NULL来调用该构造方法,会抛出空指针异常。
 * 
 * Every thread has a name for identification purposes. More than
 * one thread may have the same name. If a name is not specified when
 * a thread is created, a new name is generated for it.
 * <p>
 * Unless otherwise noted, passing a {@code null} argument to a constructor
 * or method in this class will cause a {@link NullPointerException} to be
 * thrown.
 *
 * @author  unascribed
 * @see     Runnable
 * @see     Runtime#exit(int)
 * @see     #run()
 * @see     #stop()
 * @since   JDK1.0
 */

主要属性:

    第一件事就是要本地注册。
    /* Make sure registerNatives is the first thing <clinit> does. */
    private static native void registerNatives();
    static {
        registerNatives();
    }

    private volatile String name;
    private int            priority;
    private Thread         threadQ;
    private long           eetop;

    /* 是否单步执行,但看源码中,该属性没有用到,不确定什么作用 */
    private boolean     single_step;

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

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

    /* 通过构造方法,传入的目标运行类*/
    private Runnable target;

    /* 当前线程所属的线程组 */
    private ThreadGroup group;

    /* 当前线程所属的上下文类加载器 */
    private ClassLoader contextClassLoader;

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

    /* 匿名线程自动计数器 */
    private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
        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;

    /*
     * 线程所需的栈长度,如果创建者没有指定长度,长度为0.数字依赖于具体的VM,部分VM可能会忽略。
     * 
     * 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保留的私有状态。
     * JVM-private state that persists after native thread termination.
     */
    private long nativeParkEventPointer;

    /*
     * 线程ID
     * Thread ID
     */
    private long tid;

    /* 通用线程ID */
    private static long threadSeqNumber;

    /* 线程状态,表明线程状态
    /* Java thread status for tools,
     * initialized to indicate thread 'not yet started'
     */

    private volatile int threadStatus = 0;


    private static synchronized long nextThreadID() {
        return ++threadSeqNumber;
    }

    /**
     * java.util.concurrent.locks.LockSupport.park的参数,通过java.util.concurrent.locks.LockSupport.setBlocker/getBlocker进行访问
     * 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;

    /* 线程被阻塞在可中断I/O操作(如果有的话)中的对象。在设置这个线程的中断状态后,应该调用阻塞器的interrupt方法。
     * 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;
        }
    }

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

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

    /**
     * 最大优先级
     */
    public final static int MAX_PRIORITY = 10;

方法及类源码解析如下:

package java.lang;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.security.AccessController;
import java.security.AccessControlContext;
import java.security.PrivilegedAction;
import java.util.Map;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.LockSupport;
import sun.nio.ch.Interruptible;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.security.util.SecurityConstants;



public
class Thread implements Runnable {
    /**
     * 返回当前执行线程的引用对象
     * Returns a reference to the currently executing thread object.
     *
     * @return  the currently executing thread.
     */
    public static native Thread currentThread();

    /**
     * 提示调度器,当前线程愿意放弃对处理器的占用,调度器可以忽略这个提示。
     * 
     * A hint to the scheduler that the current thread is willing to yield
     * its current use of a processor. The scheduler is free to ignore this
     * hint.
     *
     * Yield用来改善线程之间对CPU的过度使用,应该结合详细的分析和基准测试来使用,以确保它实际上具有预期的效果。
     * <p> Yield is a heuristic attempt to improve relative progression
     * between threads that would otherwise over-utilise a CPU. Its use
     * should be combined with detailed profiling and benchmarking to
     * ensure that it actually has the desired effect.
     *
     * 对于调试或测试目的来说,可能很有用,因为它可以帮助由于竞争条件而重现bug。在设计诸如java.util.concurrent并发控制结构也比较有用。
     * <p> It is rarely appropriate to use this method. It may be useful
     * for debugging or testing purposes, where it may help to reproduce
     * bugs due to race conditions. It may also be useful when designing
     * concurrency control constructs such as the ones in the
     * {@link java.util.concurrent.locks} package.
     */
    public static native void yield();

    /**
     * 
     * 睡眠指定时间(毫秒),睡眠过程中,如果有其他线程中断了当前线程,就会抛出中断异常。
     * Causes the currently executing thread to sleep (temporarily cease
     * execution) for the specified number of milliseconds, subject to
     * the precision and accuracy of system timers and schedulers. The thread
     * does not lose ownership of any monitors.
     *
     * @param  millis
     *         the length of time to sleep in milliseconds
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
	public static native void sleep(long millis) throws InterruptedException;
	/*
	 * 例子:
	 * public static void interruptThreadByOtherThread() {
	 * 	final Thread subject1 = new Thread(new Runnable() {
	 * 
	 * 		public void run() {
	 * 			try {
	 * 				Thread.sleep(20000);
	 * 			} catch (InterruptedException e) {
	 * 				e.printStackTrace();
	 * 			}
	 * 			System.out.println("subject 1 stopped!");
	 * 		}
	 * 	});
	 * 	final Thread subject2 = new Thread(new Runnable() {
	 * 
	 * 		public void run() {
	 * 			while (!Thread.interrupted()) {
	 * 				Thread.yield();
	 * 			}
	 * 			System.out.println("subject 2 stopped!");
	 * 		}
	 * 	});
	 * 	final Thread coordinator = new Thread(new Runnable() {
	 * 
	 * 		public void run() {
	 * 			try {
	 * 				Thread.sleep(500);
	 * 			} catch (InterruptedException ex) {
	 * 			}
	 * 			System.out.println("coordinator stopping!");
	 * 			subject1.interrupt();
	 * 			subject2.interrupt();
	 * 		}
	 * 	});
	 * 	subject1.start();
	 * 	subject2.start();
	 * 	coordinator.start();
	 * }
	 * 
	 * 输入结果,在睡眠过程中,被中断了:
	 * coordinator stopping!
	 * subject 2 stopped!
	 * subject 1 stopped!
	 * java.lang.InterruptedException: sleep interrupted
	 * 	at java.lang.Thread.sleep(Native Method)
	 * 	at com.geor.collection.SoureThread$2.run(SoureThread.java:99)
	 * 	at java.lang.Thread.run(Thread.java:748)	
	 */
	
	
    /**
     * 根据传入的 nanos>=50000,来确定是否在传入的 millis基础上加1,意义不是很大
     * 
     * Causes the currently executing thread to sleep (temporarily cease
     * execution) for the specified number of milliseconds plus the specified
     * number of nanoseconds, subject to the precision and accuracy of system
     * timers and schedulers. The thread does not lose ownership of any
     * monitors.
     *
     * @param  millis
     *         the length of time to sleep in milliseconds
     *
     * @param  nanos
     *         {@code 0-999999} additional nanoseconds to sleep
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative, or the value of
     *          {@code nanos} is not in the range {@code 0-999999}
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    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);
    }

    /**
     * Initializes a Thread with the current AccessControlContext.
     * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext,boolean)
     */
    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize) {
        init(g, target, name, stackSize, null, true);
    }

    /**
     * Initializes a Thread.
     *
     * @param g the Thread group
     * @param target the object whose run() method gets called
     * @param name the name of the new Thread
     * @param stackSize the desired stack size for the new thread, or
     *        zero to indicate that this parameter is to be ignored.
     * @param acc the AccessControlContext to inherit, or
     *            AccessController.getContext() if null
     * @param inheritThreadLocals if {@code true}, inherit initial values for
     *            inheritable thread-locals from the constructing thread
     */
    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();
        SecurityManager security = System.getSecurityManager();
        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) {
                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();
            }
        }

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

    /**
     * Throws CloneNotSupportedException as a Thread can not be meaningfully
     * cloned. Construct a new Thread instead.
     *
     * @throws  CloneNotSupportedException
     *          always
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }

    /**
     * 使用 Thread-整型 格式,命名创建一个新的线程
     * Allocates a new {@code Thread} object. This constructor has the same
     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
     * {
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值