Java Thread 源码 附录

1  /*
2   * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
3   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4   *
5   * This code is free software; you can redistribute it and/or modify it
6   * under the terms of the GNU General Public License version 2 only, as
7   * published by the Free Software Foundation. Oracle designates this
8   * particular file as subject to the "Classpath" exception as provided
9   * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
26  package java.lang;
28  import  java.lang.ref.Reference;
29  import  java.lang.ref.ReferenceQueue;
30  import  java.lang.ref.WeakReference;
31  import  java.security.AccessController;
32  import  java.security.AccessControlContext;
33  import  java.security.PrivilegedAction;
34  import  java.util.Map;
35  import  java.util.HashMap;
36  import  java.util.concurrent.ConcurrentHashMap;
37  import  java.util.concurrent.ConcurrentMap;
38  import  java.util.concurrent.locks.LockSupport;
39  import  sun.nio.ch.Interruptible;
40  import  sun.reflect.CallerSensitive;
41  import  sun.reflect.Reflection;
42  import  sun.security.util.SecurityConstants;

140  public
141  class Thread implements Runnable {
142      /* Make sure registerNatives is the first thing <clinit> does. */
143      private static native void registerNatives();
144      static {
145          registerNatives();
146      }
148      private volatile char  name[];
149      private int            priority;
150      private Thread         threadQ;
151      private long           eetop;
153      /* Whether or not to single_step this thread. */
154      private boolean     single_step;
156      /* Whether or not the thread is a daemon thread. */
157      private boolean     daemon = false;
159      /* JVM state */
160      private boolean     stillborn = false;
162      /* What will be run. */
163      private Runnable target;
165      /* The group of this thread */
166      private ThreadGroup group;
168      /* The context ClassLoader for this thread */
169      private ClassLoader contextClassLoader;
171      /* The inherited AccessControlContext of this thread */
172      private AccessControlContext inheritedAccessControlContext;
174      /* For autonumbering anonymous threads. */
175      private static int threadInitNumber;
176      private static synchronized int nextThreadNum() {
177          return threadInitNumber++;
178      }
180      /* ThreadLocal values pertaining to this thread. This map is maintained
181   * by the ThreadLocal class. */
182      ThreadLocal.ThreadLocalMap threadLocals = null;
184      /*
185   * InheritableThreadLocal values pertaining to this thread. This map is
186   * maintained by the InheritableThreadLocal class.
187   */
188      ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
190      /*
191   * The requested stack size for this thread, or 0 if the creator did
192   * not specify a stack size. It is up to the VM to do whatever it
193   * likes with this number; some VMs will ignore it.
194   */
195      private long stackSize;
197      /*
198   * JVM-private state that persists after native thread termination.
199   */
200      private long nativeParkEventPointer;
202      /*
203   * Thread ID
204   */
205      private long tid;
207      /* For generating thread ID */
208      private static long threadSeqNumber;
210      /* Java thread status for tools,
211   * initialized to indicate thread 'not yet started'
212   */
214      private volatile int threadStatus = 0;
217      private static synchronized long nextThreadID() {
218          return ++threadSeqNumber;
219      }

227      volatile Object parkBlocker;
229      /* The object in which this thread is blocked in an interruptible I/O
230   * operation, if any. The blocker's interrupt method should be invoked
231   * after setting this thread's interrupt status.
232   */
233      private volatile Interruptible blocker;
234      private final Object blockerLock = new Object();
236      /* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code
237   */
238      void blockedOn(Interruptible b) {
239          synchronized (blockerLock) {
240              blocker = b;
241          }
242      }

247      public final static int MIN_PRIORITY = 1;

252      public final static int NORM_PRIORITY = 5;

257      public final static int MAX_PRIORITY = 10;

264      public static native Thread currentThread();

282      public static native void yield();

301      public static native void sleep(long millis) throws InterruptedException;

325      public static void sleep(long millis, int nanos)
326      throws InterruptedException {
327          if (millis < 0) {
328              throw new IllegalArgumentException("timeout value is negative");
329          }
331          if (nanos < 0 || nanos > 999999) {
332              throw new IllegalArgumentException(
333                                  "nanosecond timeout value out of range");
334          }
336          if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
337              millis++;
338          }
340          sleep(millis);
341      }

347      private void init(ThreadGroup g, Runnable target, String name,
348                        long stackSize) {
349          init(g, target, name, stackSize, null);
350      }

363      private void init(ThreadGroup g, Runnable target, String name,
364                        long stackSize, AccessControlContext acc) {
365          if (name == null) {
366              throw new NullPointerException("name cannot be null");
367          }
369          Thread parent = currentThread();
370          SecurityManager security = System.getSecurityManager();
371          if (g == null) {
372              /* Determine if it's an applet or not */
374              /* If there is a security manager, ask the security manager
375   what to do. */
376              if (security != null) {
377                  g = security.getThreadGroup();
378              }
380              /* If the security doesn't have a strong opinion of the matter
381   use the parent thread group. */
382              if (g == null) {
383                  g = parent.getThreadGroup();
384              }
385          }
387          /* checkAccess regardless of whether or not threadgroup is
388   explicitly passed in. */
389          g.checkAccess();
391          /*
392   * Do we have the required permissions?
393   */
394          if (security != null) {
395              if (isCCLOverridden(getClass())) {
396                  security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
397              }
398          }
400          g.addUnstarted();
402          this.group = g;
403          this.daemon = parent.isDaemon();
404          this.priority = parent.getPriority();
405          this.name = name.toCharArray();
406          if (security == null || isCCLOverridden(parent.getClass()))
407              this.contextClassLoader = parent.getContextClassLoader();
408          else
409              this.contextClassLoader = parent.contextClassLoader;
410          this.inheritedAccessControlContext =
411                  acc != null ? acc : AccessController.getContext();
412          this.target = target;
413          setPriority(priority);
414          if (parent.inheritableThreadLocals != null)
415              this.inheritableThreadLocals =
416                  ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
417          /* Stash the specified stack size in case the VM cares */
418          this.stackSize = stackSize;
420          /* Set thread ID */
421          tid = nextThreadID();
422      }

431      @Override
432      protected Object clone() throws CloneNotSupportedException {
433          throw new CloneNotSupportedException();
434      }

443      public Thread() {
444          init(null, null, "Thread-" + nextThreadNum(), 0);
445      }

459      public Thread(Runnable target) {
460          init(null, target, "Thread-" + nextThreadNum(), 0);
461      }

467      Thread(Runnable target, AccessControlContext acc) {
468          init(null, target, "Thread-" + nextThreadNum(), 0, acc);
469      }

494      public Thread(ThreadGroup group, Runnable target) {
495          init(group, target, "Thread-" + nextThreadNum(), 0);
496      }

506      public Thread(String name) {
507          init(null, null, name, 0);
508      }

530      public Thread(ThreadGroup group, String name) {
531          init(group, null, name, 0);
532      }

546      public Thread(Runnable target, String name) {
547          init(null, target, name, 0);
548      }

594      public Thread(ThreadGroup group, Runnable target, String name) {
595          init(group, target, name, 0);
596      }

672      public Thread(ThreadGroup group, Runnable target, String name,
673                    long stackSize) {
674          init(group, target, name, stackSize);
675      }

695      public synchronized void start() {

703          if (threadStatus != 0)
704              throw new IllegalThreadStateException();
706          /* Notify the group that this thread is about to be started
707   * so that it can be added to the group's list of threads
708   * and the group's unstarted count can be decremented. */
709          group.add(this);
711          boolean started = false;
712          try {
713              start0();
714              started = true;
715          } finally {
716              try {
717                  if (!started) {
718                      group.threadStartFailed(this);
719                  }
720              } catch (Throwable ignore) {
721                  /* do nothing. If start0 threw a Throwable then
722   it will be passed up the call stack */
723              }
724          }
725      }
727      private native void start0();

741      @Override
742      public void run() {
743          if (target != null) {
744              target.run();
745          }
746      }

752      private void exit() {
753          if (group != null) {
754              group.threadTerminated(this);
755              group = null;
756          }
757          /* Aggressively null out all reference fields: see bug 4006245 */
758          target = null;
759          /* Speed the release of some of these resources */
760          threadLocals = null;
761          inheritableThreadLocals = null;
762          inheritedAccessControlContext = null;
763          blocker = null;
764          uncaughtExceptionHandler = null;
765      }

833      @Deprecated
834      public final void stop() {
835          SecurityManager security = System.getSecurityManager();
836          if (security != null) {
837              checkAccess();
838              if (this != Thread.currentThread()) {
839                  security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
840              }
841          }
842          // A zero status value corresponds to "NEW", it can't change to
843          // not-NEW because we hold the lock.
844          if (threadStatus != 0) {
845              resume(); // Wake up thread if it was suspended; no-op otherwise
846          }
848          // The VM can handle all thread states
849          stop0(new ThreadDeath());
850      }

866      @Deprecated
867      public final synchronized void stop(Throwable obj) {
868          throw new UnsupportedOperationException();
869      }

910      public void interrupt() {
911          if (this != Thread.currentThread())
912              checkAccess();
914          synchronized (blockerLock) {
915              Interruptible b = blocker;
916              if (b != null) {
917                  interrupt0();           // Just to set the interrupt flag
918                  b.interrupt(this);
919                  return;
920              }
921          }
922          interrupt0();
923      }

942      public static boolean interrupted() {
943          return currentThread().isInterrupted(true);
944      }

959      public boolean isInterrupted() {
960          return isInterrupted(false);
961      }

968      private native boolean isInterrupted(boolean ClearInterrupted);

987      @Deprecated
988      public void destroy() {
989          throw new NoSuchMethodError();
990      }

999      public final native boolean isAlive();

1025      @Deprecated
1026      public final void suspend() {
1027          checkAccess();
1028          suspend0();
1029      }

1051      @Deprecated
1052      public final void resume() {
1053          checkAccess();
1054          resume0();
1055      }

1081      public final void setPriority(int newPriority) {
1082          ThreadGroup g;
1083          checkAccess();
1084          if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
1085              throw new IllegalArgumentException();
1086          }
1087          if((g = getThreadGroup()) != null) {
1088              if (newPriority > g.getMaxPriority()) {
1089                  newPriority = g.getMaxPriority();
1090              }
1091              setPriority0(priority = newPriority);
1092          }
1093      }

1101      public final int getPriority() {
1102          return priority;
1103      }

1119      public final synchronized void setName(String name) {
1120          checkAccess();
1121          this.name = name.toCharArray();
1122          if (threadStatus != 0) {
1123              setNativeName(name);
1124          }
1125      }

1133      public final String getName() {
1134          return new String(name, true);
1135      }

1144      public final ThreadGroup getThreadGroup() {
1145          return group;
1146      }

1164      public static int activeCount() {
1165          return currentThread().getThreadGroup().activeCount();
1166      }

1194      public static int enumerate(Thread tarray[]) {
1195          return currentThread().getThreadGroup().enumerate(tarray);
1196      }

1209      @Deprecated
1210      public native int countStackFrames();

1233      public final synchronized void join(long millis)
1234      throws InterruptedException {
1235          long base = System.currentTimeMillis();
1236          long now = 0;
1238          if (millis < 0) {
1239              throw new IllegalArgumentException("timeout value is negative");
1240          }
1242          if (millis == 0) {
1243              while (isAlive()) {
1244                  wait(0);
1245              }
1246          } else {
1247              while (isAlive()) {
1248                  long delay = millis - now;
1249                  if (delay <= 0) {
1250                      break;
1251                  }
1252                  wait(delay);
1253                  now = System.currentTimeMillis() - base;
1254              }
1255          }
1256      }

1283      public final synchronized void join(long millis, int nanos)
1284      throws InterruptedException {
1286          if (millis < 0) {
1287              throw new IllegalArgumentException("timeout value is negative");
1288          }
1290          if (nanos < 0 || nanos > 999999) {
1291              throw new IllegalArgumentException(
1292                                  "nanosecond timeout value out of range");
1293          }
1295          if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
1296              millis++;
1297          }
1299          join(millis);
1300      }

1317      public final void join() throws InterruptedException {
1318          join(0);
1319      }

1327      public static void dumpStack() {
1328          new Exception("Stack trace").printStackTrace();
1329      }

1348      public final void setDaemon(boolean on) {
1349          checkAccess();
1350          if (isAlive()) {
1351              throw new IllegalThreadStateException();
1352          }
1353          daemon = on;
1354      }

1363      public final boolean isDaemon() {
1364          return daemon;
1365      }

1379      public final void checkAccess() {
1380          SecurityManager security = System.getSecurityManager();
1381          if (security != null) {
1382              security.checkAccess(this);
1383          }
1384      }

1392      public String toString() {
1393          ThreadGroup group = getThreadGroup();
1394          if (group != null) {
1395              return "Thread[" + getName() + "," + getPriority() + "," +
1396                             group.getName() + "]";
1397          } else {
1398              return "Thread[" + getName() + "," + getPriority() + "," +
1399                              "" + "]";
1400          }
1401      }

1429      @CallerSensitive
1430      public ClassLoader getContextClassLoader() {
1431          if (contextClassLoader == null)
1432              return null;
1433          SecurityManager sm = System.getSecurityManager();
1434          if (sm != null) {
1435              ClassLoader.checkClassLoaderPermission(contextClassLoader,
1436                                                     Reflection.getCallerClass());
1437          }
1438          return contextClassLoader;
1439      }

1463      public void setContextClassLoader(ClassLoader cl) {
1464          SecurityManager sm = System.getSecurityManager();
1465          if (sm != null) {
1466              sm.checkPermission(new RuntimePermission("setContextClassLoader"));
1467          }
1468          contextClassLoader = cl;
1469      }

1487      public static native boolean holdsLock(Object obj);
1489      private static final StackTraceElement[] EMPTY_STACK_TRACE
1490          = new StackTraceElement[0];

1528      public StackTraceElement[] getStackTrace() {
1529          if (this != Thread.currentThread()) {
1530              // check for getStackTrace permission
1531              SecurityManager security = System.getSecurityManager();
1532              if (security != null) {
1533                  security.checkPermission(
1534                      SecurityConstants.GET_STACK_TRACE_PERMISSION);
1535              }
1536              // optimization so we do not call into the vm for threads that
1537              // have not yet started or have terminated
1538              if (!isAlive()) {
1539                  return EMPTY_STACK_TRACE;
1540              }
1541              StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this});
1542              StackTraceElement[] stackTrace = stackTraceArray[0];
1543              // a thread that was alive during the previous isAlive call may have
1544              // since terminated, therefore not having a stacktrace.
1545              if (stackTrace == null) {
1546                  stackTrace = EMPTY_STACK_TRACE;
1547              }
1548              return stackTrace;
1549          } else {
1550              // Don't need JVM help for current thread
1551              return (new Exception()).getStackTrace();
1552          }
1553      }

1590      public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
1591          // check for getStackTrace permission
1592          SecurityManager security = System.getSecurityManager();
1593          if (security != null) {
1594              security.checkPermission(
1595                  SecurityConstants.GET_STACK_TRACE_PERMISSION);
1596              security.checkPermission(
1597                  SecurityConstants.MODIFY_THREADGROUP_PERMISSION);
1598          }
1600          // Get a snapshot of the list of all threads
1601          Thread[] threads = getThreads();
1602          StackTraceElement[][] traces = dumpThreads(threads);
1603          Map<Thread, StackTraceElement[]> m = new HashMap<>(threads.length);
1604          for (int i = 0; i < threads.length; i++) {
1605              StackTraceElement[] stackTrace = traces[i];
1606              if (stackTrace != null) {
1607                  m.put(threads[i], stackTrace);
1608              }
1609              // else terminated so we don't put it in the map
1610          }
1611          return m;
1612      }
1615      private static final RuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION =
1616                      new RuntimePermission("enableContextClassLoaderOverride");

1619      /* Replace with ConcurrentReferenceHashMap when/if it appears in a future
1620   * release */
1621      private static class Caches {

1623          static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
1624              new ConcurrentHashMap<>();

1627          static final ReferenceQueue<Class<?>> subclassAuditsQueue =
1628              new ReferenceQueue<>();
1629      }

1637      private static boolean isCCLOverridden(Class<?> cl) {
1638          if (cl == Thread.class)
1639              return false;
1641          processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
1642          WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
1643          Boolean result = Caches.subclassAudits.get(key);
1644          if (result == null) {
1645              result = Boolean.valueOf(auditSubclass(cl));
1646              Caches.subclassAudits.putIfAbsent(key, result);
1647          }
1649          return result.booleanValue();
1650      }

1657      private static boolean auditSubclass(final Class<?> subcl) {
1658          Boolean result = AccessController.doPrivileged(
1659              new PrivilegedAction<Boolean>() {
1660                  public Boolean run() {
1661                      for (Class<?> cl = subcl;
1662                           cl != Thread.class;
1663                           cl = cl.getSuperclass())
1664                      {
1665                          try {
1666                              cl.getDeclaredMethod("getContextClassLoader", new Class<?>[0]);
1667                              return Boolean.TRUE;
1668                          } catch (NoSuchMethodException ex) {
1669                          }
1670                          try {
1671                              Class<?>[] params = {ClassLoader.class};
1672                              cl.getDeclaredMethod("setContextClassLoader", params);
1673                              return Boolean.TRUE;
1674                          } catch (NoSuchMethodException ex) {
1675                          }
1676                      }
1677                      return Boolean.FALSE;
1678                  }
1679              }
1680          );
1681          return result.booleanValue();
1682      }
1684      private native static StackTraceElement[][] dumpThreads(Thread[] threads);
1685      private native static Thread[] getThreads();

1696      public long getId() {
1697          return tid;
1698      }

1734      public enum State {

1738          NEW,

1746          RUNNABLE,

1755          BLOCKED,

1776          WAITING,

1790          TIMED_WAITING,

1796          TERMINATED;
1797      }

1807      public State getState() {
1808          // get current thread state
1809          return sun.misc.VM.toThreadState(threadStatus);
1810      }
1812      // Added in JSR-166
1813  

1836      @FunctionalInterface
1837      public interface UncaughtExceptionHandler {

1846          void uncaughtException(Thread t, Throwable e);
1847      }
1849      // null unless explicitly set
1850      private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
1852      // null unless explicitly set
1853      private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;

1889      public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
1890          SecurityManager sm = System.getSecurityManager();
1891          if (sm != null) {
1892              sm.checkPermission(
1893                  new RuntimePermission("setDefaultUncaughtExceptionHandler")
1894                      );
1895          }
1897           defaultUncaughtExceptionHandler = eh;
1898       }

1908      public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){
1909          return defaultUncaughtExceptionHandler;
1910      }

1921      public UncaughtExceptionHandler getUncaughtExceptionHandler() {
1922          return uncaughtExceptionHandler != null ?
1923              uncaughtExceptionHandler : group;
1924      }

1941      public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
1942          checkAccess();
1943          uncaughtExceptionHandler = eh;
1944      }

1950      private void dispatchUncaughtException(Throwable e) {
1951          getUncaughtExceptionHandler().uncaughtException(this, e);
1952      }

1958      static void processQueue(ReferenceQueue<Class<?>> queue,
1959                               ConcurrentMap<? extends
1960                               WeakReference<Class<?>>, ?> map)
1961      {
1962          Reference<? extends Class<?>> ref;
1963          while((ref = queue.poll()) != null) {
1964              map.remove(ref);
1965          }
1966      }

1971      static class WeakClassKey extends WeakReference<Class<?>> {

1976          private final int hash;

1982          WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) {
1983              super(cl, refQueue);
1984              hash = System.identityHashCode(cl);
1985          }

1990          @Override
1991          public int hashCode() {
1992              return hash;
1993          }

2001          @Override
2002          public boolean equals(Object obj) {
2003              if (obj == this)
2004                  return true;
2006              if (obj instanceof WeakClassKey) {
2007                  Object referent = get();
2008                  return (referent != null) &&
2009                         (referent == ((WeakClassKey) obj).get());
2010              } else {
2011                  return false;
2012              }
2013          }
2014      }
2017      // The following three initially uninitialized fields are exclusively
2018      // managed by class java.util.concurrent.ThreadLocalRandom. These
2019      // fields are used to build the high-performance PRNGs in the
2020      // concurrent code, and we can not risk accidental false sharing.
2021      // Hence, the fields are isolated with @Contended.
2022  

2024      @sun.misc.Contended("tlr")
2025      long threadLocalRandomSeed;

2028      @sun.misc.Contended("tlr")
2029      int threadLocalRandomProbe;

2032      @sun.misc.Contended("tlr")
2033      int threadLocalRandomSecondarySeed;
2035      /* Some private helper methods */
2036      private native void setPriority0(int newPriority);
2037      private native void stop0(Object o);
2038      private native void suspend0();
2039      private native void resume0();
2040      private native void interrupt0();
2041      private native void setNativeName(String name);
2042  }

你可能感兴趣的:(Java Thread 源码 附录)