1、start方法html
一个线程一旦已经被start了就不能再次执行start方法。被start过的线程,线程状态已经不是0了,线程状态总共有5种状态java
//线程启动执行,jvm调用线程的run方法 //产生的结果是由两个线程同时运行,一个是当前线程调用start方法的线程,一个是 //执行run方法的线程。 /** * 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() { //这个方法不是给main方法线程或者VM建立的系统组线程调用的。任何将来可能被添加到该 //方法的功能,未来也许会同时加到虚拟机。状态0表示状态 NEW。一旦线程被启动以后该值 //将会被改变,同一线程被启动屡次就会出现异常,不论是执行中仍是执行完成该线程都不能 //再次被start。若是一个线程正在执行中进行start,该值为2表示是Runnable,若是该值为5 //则表示为Terminated。 /** * 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) 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); //是否启动 boolean started = false; try { //调用线程本地方法 start0(); 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();
2、join方法bootstrap
join方法本质上调用的是Object的wait方法,线程结束时会调用Object的唤醒方法。数组
//等待线程执行完成最多指定毫秒数时间。0,表示永不超时。该实现用的是循环等待 //鉴于,线程终止时notifyAll方法将被调用,因此不建议应用在Thread实例对象使用 //wait,notify或者notifyAll方法。 /** * Waits at most {@code millis} milliseconds for this thread to * die. A timeout of {@code 0} means to wait forever. * * <p> This implementation uses a loop of {@code this.wait} calls * conditioned on {@code this.isAlive}. As a thread terminates the * {@code this.notifyAll} method is invoked. It is recommended that * applications not use {@code wait}, {@code notify}, or * {@code notifyAll} on {@code Thread} instances. * * @param millis * the time to wait 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 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()) { //调用Object的wait方法 wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } } }
3、interrupt方法安全
线程中断方法,当代码调用sleep,join,wait的方法时,咱们都会被要求显示捕获InterruptedException,这就是当线程被外部中断时,当执行到这个地方的时候会被中断。并发
//除非中断本身,checkAccess都将被调用 /** * Interrupts this thread. * * <p> Unless the current thread is interrupting itself, which is * always permitted, the {@link #checkAccess() checkAccess} method * of this thread is invoked, which may cause a {@link * SecurityException} to be thrown. * //若是一个线程阻塞在wat方法,或者线程的join方法,再或者sleep方法上, //线程的中断状态被清空设置为false,而且被interrupt的线程将收到一个中断异常。 * <p> If this thread is blocked in an invocation of the {@link * Object#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link * Object#wait(long, int) wait(long, int)} methods of the {@link Object} * class, or of the {@link #join()}, {@link #join(long)}, {@link * #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)}, * methods of this class, then its interrupt status will be cleared and it * will receive an {@link InterruptedException}. * //若是线程阻塞在IO操做,channel将被关闭,而且线程的中断状态会被设置为true, //而且被interrupt的线程将收到一个ClosedByInterruptException异常。 * <p> If this thread is blocked in an I/O operation upon an {@link * java.nio.channels.InterruptibleChannel InterruptibleChannel} * then the channel will be closed, the thread's interrupt * status will be set, and the thread will receive a {@link * java.nio.channels.ClosedByInterruptException}. * //若是线程阻塞在selector方法,中断线程的中断状态将设置为true,而且从select操做当即返回, //只有selector的wakeup方法被调用可能返回一个非0值。 * <p> If this thread is blocked in a {@link java.nio.channels.Selector} * then the thread's interrupt status will be set and it will return * immediately from the selection operation, possibly with a non-zero * value, just as if the selector's {@link * java.nio.channels.Selector#wakeup wakeup} method were invoked. *//若是不是上面说的几种状况,线程的中断状态将被设置。 * <p> If none of the previous conditions hold then this thread's interrupt * status will be set. </p> * * <p> Interrupting a thread that is not alive need not have any effect. * * @throws SecurityException * if the current thread cannot modify this thread * * @revised 6.0 * @spec JSR-51 */ 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(); }
4、setPriorityapp
设置线程优先级,优先得到执行权,默认优先级是5,最小优先级是1,最大优先级是10less
//改变线程优先级。 //首先执行checkAccess查看权限。最小被设置为指定的值,最大为线程组的值。 //根据此能够发现一个线程设置优先级必须归属于某个线程组。 /** * Changes the priority of this thread. * <p> * First the <code>checkAccess</code> method of this thread is called * with no arguments. This may result in throwing a * <code>SecurityException</code>. * <p> * Otherwise, the priority of this thread is set to the smaller of * the specified <code>newPriority</code> and the maximum permitted * priority of the thread's thread group. * * @param newPriority priority to set this thread to * @exception IllegalArgumentException If the priority is not in the * range <code>MIN_PRIORITY</code> to * <code>MAX_PRIORITY</code>. * @exception SecurityException if the current thread cannot modify * this thread. * @see #getPriority * @see #checkAccess() * @see #getThreadGroup() * @see #MAX_PRIORITY * @see #MIN_PRIORITY * @see ThreadGroup#getMaxPriority() */ 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); } }
5、yield方法jvm
让出处理器使用ide
//示意线程调度器,当前线程但愿让出正在使用的处理器。调度器能够忽略此请求。 //让出是探索式的尝试,目的是提升线程间相对运行进展不致于某个线程过分使用CPU。 //yield的使用应该结合详细的文档分析和不断基准测试来保证它真正实现指望的效果。 //不多有合适场合使用此方法。对以测试为目的的debug也许是有用的,好比由于竞争条件 //复现一线bug。设计并发控制结构也可能颇有用,好比concurrent.locks包并发控制结构中 //就有一些使用yield方法。 /** * 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();
6、sleep方法
//让当前执行的线程睡眠指定的时间。当前线程不会失去任何监视器的拥有权。 /** * 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;
7、init线程
当new Thread一个线程时将执行init方法,Thread构造器会调用到这个方法。
/** * 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 */ 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(); //若是线程组为null 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? //校验是否有安全校验权利,若是重写了getContextClassLoader和setContextClassLoader */ 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 (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(); }
8、线程状态
public enum State { //线程还没有启动时处于此状态 /** * Thread state for a thread which has not yet started. */ NEW, //容许中的线程状态,runnable表示线程在jvm中运行可是可能在等待操做系统的其余资源,好比处理器 /** * Thread state for a runnable thread. A thread in the runnable * state is executing in the Java virtual machine but it may * be waiting for other resources from the operating system * such as processor. */ RUNNABLE, //线程阻塞在等待监视器的锁,线程处于blocked状态是指它在等待监视器锁来进如同步的方法或者块或者是在调用了wait方法后从新进入一个同步 //方法或者同步块。 /** * Thread state for a thread blocked waiting for a monitor lock. * A thread in the blocked state is waiting for a monitor lock * to enter a synchronized block/method or * reenter a synchronized block/method after calling * {@link Object#wait() Object.wait}. */ BLOCKED, //处于等待状态的线程,在调用未设置超时的object的wait()方法,或者Thread的join(),或者LockSupport.park()方法后 //线程处于等待状态是指在等待另一个线程执行特殊操做。例如线程调用object的wait以后等待另一个线程执行notify //或者notifyAll方法。线程调用Thread.join是在等待指定的线程终止以后执行操做。 /** * Thread state for a waiting thread. * A thread is in the waiting state due to calling one of the * following methods: * <ul> * <li>{@link Object#wait() Object.wait} with no timeout</li> * <li>{@link #join() Thread.join} with no timeout</li> * <li>{@link LockSupport#park() LockSupport.park}</li> * </ul> * * <p>A thread in the waiting state is waiting for another thread to * perform a particular action. * * For example, a thread that has called <tt>Object.wait()</tt> * on an object is waiting for another thread to call * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on * that object. A thread that has called <tt>Thread.join()</tt> * is waiting for a specified thread to terminate. */ WAITING, //指定时间的等待,线程处于此状态是因为调用以下方法指定正数等待时间: //Thread.sleep,Object.wait,Thread.join,LockSupport.parkNanos,LockSupport.parkUntil /** * Thread state for a waiting thread with a specified waiting time. * A thread is in the timed waiting state due to calling one of * the following methods with a specified positive waiting time: * <ul> * <li>{@link #sleep Thread.sleep}</li> * <li>{@link Object#wait(long) Object.wait} with timeout</li> * <li>{@link #join(long) Thread.join} with timeout</li> * <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li> * <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li> * </ul> */ TIMED_WAITING, //线程结束状态,表示线程已经完成执行。 /** * Thread state for a terminated thread. * The thread has completed execution. */ TERMINATED; }
9、被弃用的方法
stop,suspend,resume都再也不使用
//挂起当前线程。checkAccess校验权限。若是线程存活时被挂起,将不会继续执行, //直到调用resume方法。 //由于容易引发死锁,该方法已经被弃用。好比,目标线程持有一个重要资源的锁时被 //挂起,直到目标线程被恢复将没有线程能够访问这个资源。若是恢复目标线程的线程尝试在调用 //resume方法以前优先锁住资源的监视器将产生死锁。同stop,resume同样都被弃用。 /** * Suspends this thread. * <p> * First, the <code>checkAccess</code> method of this thread is called * with no arguments. This may result in throwing a * <code>SecurityException </code>(in the current thread). * <p> * If the thread is alive, it is suspended and makes no further * progress unless and until it is resumed. * * @exception SecurityException if the current thread cannot modify * this thread. * @see #checkAccess * @deprecated This method has been deprecated, as it is * inherently deadlock-prone. If the target thread holds a lock on the * monitor protecting a critical system resource when it is suspended, no * thread can access this resource until the target thread is resumed. If * the thread that would resume the target thread attempts to lock this * monitor prior to calling <code>resume</code>, deadlock results. Such * deadlocks typically manifest themselves as "frozen" processes. * For more information, see * <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why * are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. */ @Deprecated public final void suspend() { checkAccess(); suspend0(); }
10、enumerate方法
//将本线程所属线程组及其子组中存活的线程拷贝到指定的线程数组中。该线程简单的调用 //线程组的enumerate方法。应用也许会使用activeCount()方法来获取数组的大体大小,然而,若是 //数组过小不可以保存全部线程,多出的线程将被忽略。若是获取当前线程所属线程组和子组的存活线程 //是个重要的事儿,调用者应该确认返回的值应该严格小于数组的长度。 /** * Copies into the specified array every active thread in the current * thread's thread group and its subgroups. This method simply * invokes the {@link java.lang.ThreadGroup#enumerate(Thread[])} * method of the current thread's thread group. * * <p> An application might use the {@linkplain #activeCount activeCount} * method to get an estimate of how big the array should be, however * <i>if the array is too short to hold all the threads, the extra threads * are silently ignored.</i> If it is critical to obtain every active * thread in the current thread's thread group and its subgroups, the * invoker should verify that the returned int value is strictly less * than the length of {@code tarray}. * * <p> Due to the inherent race condition in this method, it is recommended * that the method only be used for debugging and monitoring purposes. * * @param tarray * an array into which to put the list of threads * * @return the number of threads put into the array * * @throws SecurityException * if {@link java.lang.ThreadGroup#checkAccess} determines that * the current thread cannot access its thread group */ public static int enumerate(Thread tarray[]) { return currentThread().getThreadGroup().enumerate(tarray); }
11、上下文类加载器
//返回线程的上下文类加载器。上下文类加载器是由线程建立者提供,当线程须要加载类 //或者资源时使用。若是没有设置上下文类加载器,缺省的类加载器上下文是父线程。原始线程 //的上下文类加载器一般是告诉类加载器加载应用。若是存在安全管理器,调用者的类加载器不为null //这个方法将调用安全管理器的checkPermission(),将会校验是否容许返回上下文类加载器。 /** * Returns the context ClassLoader for this Thread. The context * ClassLoader is provided by the creator of the thread for use * by code running in this thread when loading classes and resources. * If not {@linkplain #setContextClassLoader set}, the default is the * ClassLoader context of the parent Thread. The context ClassLoader of the * primordial thread is typically set to the class loader used to load the * application. * * <p>If a security manager is present, and the invoker's class loader is not * {@code null} and is not the same as or an ancestor of the context class * loader, then this method invokes the security manager's {@link * SecurityManager#checkPermission(java.security.Permission) checkPermission} * method with a {@link RuntimePermission RuntimePermission}{@code * ("getClassLoader")} permission to verify that retrieval of the context * class loader is permitted. * * @return the context ClassLoader for this Thread, or {@code null} * indicating the system class loader (or, failing that, the * bootstrap class loader) * * @throws SecurityException * if the current thread cannot get the context ClassLoader * * @since 1.2 */ @CallerSensitive public ClassLoader getContextClassLoader() { if (contextClassLoader == null) return null; SecurityManager sm = System.getSecurityManager(); if (sm != null) { ClassLoader.checkClassLoaderPermission(contextClassLoader, Reflection.getCallerClass()); } return contextClassLoader; } //设置线程的上下文类加载器。上下文类加载器在线程建立时设置,并容许线程建立者提供合适的类加载器来对应到代码, //经过getContextClassLoader()来获取类加载器来加载类和资源以处理线程中运行的代码。 /** * Sets the context ClassLoader for this Thread. The context * ClassLoader can be set when a thread is created, and allows * the creator of the thread to provide the appropriate class loader, * through {@code getContextClassLoader}, to code running in the thread * when loading classes and resources. * * <p>If a security manager is present, its {@link * SecurityManager#checkPermission(java.security.Permission) checkPermission} * method is invoked with a {@link RuntimePermission RuntimePermission}{@code * ("setContextClassLoader")} permission to see if setting the context * ClassLoader is permitted. * * @param cl * the context ClassLoader for this Thread, or null indicating the * system class loader (or, failing that, the bootstrap class loader) * * @throws SecurityException * if the current thread cannot set the context ClassLoader * * @since 1.2 */ public void setContextClassLoader(ClassLoader cl) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new RuntimePermission("setContextClassLoader")); } contextClassLoader = cl; }