类简介:
/**
* 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
* . . .
* }
* }
* </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
* . . .
* }
* }
* </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}
* {