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.security.util.SecurityConstants; class Thread implements Runnable { /* Make sure registerNatives is the first thing <clinit> does. */ private static native void registerNatives(); static { registerNatives(); } private char name[]; private int priority; private Thread threadQ; private long eetop; /* 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; /* 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() { 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; /* For generating thread ID */ private static long threadSeqNumber; /* Java thread status for tools, * initialized to indicate thread 'not yet started' */ ; private static synchronized long nextThreadID() { 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. */ ; /** * The default priority that is assigned to a thread. */ ; /** * The maximum priority that a thread can have. */ ; /** * 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. * * <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. * * <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(); public static native void sleep(long millis) throws InterruptedException; /** * 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 { ) { throw new IllegalArgumentException("timeout value is negative"); } || nanos > ) { throw new IllegalArgumentException( "nanosecond timeout value out of range"); } || (nanos != && millis == )) { millis++; } sleep(millis); } /** * 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. */ private void init(ThreadGroup g, Runnable target, String name, long stackSize) { if (name == null) { throw new NullPointerException("name cannot be null"); } 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(); this.name = name.toCharArray(); if (security == null || isCCLOverridden(parent.getClass())) this.contextClassLoader = parent.getContextClassLoader(); else this.contextClassLoader = parent.contextClassLoader; this.inheritedAccessControlContext = AccessController.getContext(); this.target = target; setPriority(priority); if (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(); } public Thread() { init(); } public Thread(Runnable target) { init(); } public Thread(ThreadGroup group, Runnable target) { init(group, target, ); } public Thread(String name) { init(); } public Thread(ThreadGroup group, String name) { init(group, ); } public Thread(Runnable target, String name) { init(); } public Thread(ThreadGroup group, Runnable target, String name) { init(group, target, name, ); } /** * Allocates a new {@code Thread} object so that it has {@code target} * as its run object, has the specified {@code name} as its name, * and belongs to the thread group referred to by {@code group}, and has * the specified <i>stack size</i>. * * <p>This constructor is identical to {@link * #Thread(ThreadGroup,Runnable,String)} with the exception of the fact * that it allows the thread stack size to be specified. The stack size * is the approximate number of bytes of address space that the virtual * machine is to allocate for this thread's stack. <b>The effect of the * {@code stackSize} parameter, if any, is highly platform dependent.</b> * * <p>On some platforms, specifying a higher value for the * {@code stackSize} parameter may allow a thread to achieve greater * recursion depth before throwing a {@link StackOverflowError}. * Similarly, specifying a lower value may allow a greater number of * threads to exist concurrently without throwing an {@link * OutOfMemoryError} (or other internal error). The details of * the relationship between the value of the <tt>stackSize</tt> parameter * and the maximum recursion depth and concurrency level are * platform-dependent. <b>On some platforms, the value of the * {@code stackSize} parameter may have no effect whatsoever.</b> * * <p>The virtual machine is free to treat the {@code stackSize} * parameter as a suggestion. If the specified value is unreasonably low * for the platform, the virtual machine may instead use some * platform-specific minimum value; if the specified value is unreasonably * high, the virtual machine may instead use some platform-specific * maximum. Likewise, the virtual machine is free to round the specified * value up or down as it sees fit (or to ignore it completely). * * <p>Specifying a value of zero for the {@code stackSize} parameter will * cause this constructor to behave exactly like the * {@code Thread(ThreadGroup, Runnable, String)} constructor. * * <p><i>Due to the platform-dependent nature of the behavior of this * constructor, extreme care should be exercised in its use. * The thread stack size necessary to perform a given computation will * likely vary from one JRE implementation to another. In light of this * variation, careful tuning of the stack size parameter may be required, * and the tuning may need to be repeated for each JRE implementation on * which an application is to run.</i> * * <p>Implementation note: Java platform implementers are encouraged to * document their implementation's behavior with respect to the * {@code stackSize} parameter. * * * @param group * the thread group. If {@code null} and there is a security * manager, the group is determined by {@linkplain * SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}. * If there is not a security manager or {@code * SecurityManager.getThreadGroup()} returns {@code null}, the group * is set to the current thread's thread group. * * @param target * the object whose {@code run} method is invoked when this thread * is started. If {@code null}, this thread's run method is invoked. * * @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. * * @throws SecurityException * if the current thread cannot create a thread in the specified * thread group * * @since 1.4 */ public Thread(ThreadGroup group, Runnable target, String name, long stackSize) { init(group, target, name, stackSize); } /** * Causes this thread to begin execution; the Java Virtual Machine * calls the <code>run</code> method of this thread. * <p> * The result is that two threads are running concurrently(协调发生): the * current thread (which returns from the call to the * <code>start</code> method) and the other thread (which executes its * <code>run</code> method). * <p> * It is never legal to start a thread more than once. * In particular, a thread may not be restarted once it has completed * execution. * * @exception IllegalThreadStateException if the thread was already * started. * @see #run() * @see #stop() */ public synchronized void start() { /**(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". */ ) 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(累加器减1). */ group.add(this); boolean started = false; try { start0(); started = true; } finally { try { //之所以进行start是否为true的判断,是因为可能存在线程成功启动但是还是存在异常的情况 if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */ } } } //native方法是通过加载本地C/C++方法得到的 private native void start0(); /**对start0()方法的解释 * If this thread was constructed using a separate * <code>Runnable</code> run object, then that * <code>Runnable</code> object's <code>run</code> method is called; * otherwise, this method does nothing and returns. * <p> * Subclasses of <code>Thread</code> should override this method. * * @see #start() * @see #stop() * @see #Thread(ThreadGroup, Runnable, String) */ @Override public void run() { if (target != null) { target.run(); } }
个人认为阅读源代码的作用:1.了解工作原理 2.了解设计技巧
一点启发:1.对于存在形参不同的多个构造方法的类可以写一个具有所有参数的初始化方法,然后再在构造方法里面引用。
2.对于两种烂熟于心的两种创建线程的方法有了实质性的理解
创建线程:
1.new Thread(new Runnable()).start();首先调用构造函数,初始化时将Runnable对象赋给target,start方法中执行start0(执行Thread的run方法,target.run())
2.class Thread1 extends Thread{public void run(){}} new Thread1().start();没有Runnable的赋值,start0依然执行Thread的run方法,但是由于子类Thread1覆盖Thread的run方法,这是就是执行了Thread1里面的run方法了;
wonderful!!
3.并发问题,异常的处理
4.该源代码体现了那些具有生命周期的抽象概念的实质。例如Thread,Servlet,Filter,interceptor等等。
生命周期内:
1.只初始化一次(如何实现) : 通过构造方法,调用初始化方法,完成必要的初始化,之后就不再调用初始化方法。
2.运行(期间进行一些必要的控制,例如只能运行一次,持续运行): 对内部变量进行控制,对象锁,设置while循环等
3.销毁:对计数变量的操作,资源的释放