packagejava.lang;/**
* ...
* @author Arthur van Hoff
* @see java.lang.Thread
* @see java.util.concurrent.Callable
* @since JDK1.0
*/@FunctionalInterfacepublicinterfaceRunnable{publicabstractvoidrun();}
3 Callable
packagejava.util.concurrent;/**
* ...
* @see Executor
* @since 1.5
* @author Doug Lea
* @param <V> the result type of method {@code call}
*/@FunctionalInterfacepublicinterfaceCallable<V>{/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/Vcall()throwsException;}
4 Thead
packagejava.lang;importjava.lang.ref.Reference;importjava.lang.ref.ReferenceQueue;importjava.lang.ref.WeakReference;importjava.security.AccessController;importjava.security.AccessControlContext;importjava.security.PrivilegedAction;importjava.util.Map;importjava.util.HashMap;importjava.util.concurrent.ConcurrentHashMap;importjava.util.concurrent.ConcurrentMap;importjava.util.concurrent.locks.LockSupport;importsun.nio.ch.Interruptible;importsun.reflect.CallerSensitive;importsun.reflect.Reflection;importsun.security.util.SecurityConstants;publicclassThreadimplementsRunnable{/* Make sure registerNatives is the first thing <clinit> does. */privatestaticnativevoidregisterNatives();static{registerNatives();}privatevolatileString name;privateint priority;privateThread threadQ;privatelong eetop;/* Whether or not to single_step this thread. */privateboolean single_step;/* Whether or not the thread is a daemon thread. */privateboolean daemon =false;/* JVM state */privateboolean stillborn =false;/* What will be run. */privateRunnable target;/* The group of this thread */privateThreadGroup group;/* The context ClassLoader for this thread */privateClassLoader contextClassLoader;/* The inherited AccessControlContext of this thread */privateAccessControlContext inheritedAccessControlContext;/* For autonumbering anonymous threads. */privatestaticint threadInitNumber;privatestaticsynchronizedintnextThreadNum(){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.
*/privatelong stackSize;/*
* JVM-private state that persists after native thread termination.
*/privatelong nativeParkEventPointer;/*
* Thread ID
*/privatelong tid;/* For generating thread ID */privatestaticlong threadSeqNumber;/* Java thread status for tools,
* initialized to indicate thread 'not yet started'
*/privatevolatileint threadStatus =0;privatestaticsynchronizedlongnextThreadID(){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
*/volatileObject 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.
*/privatevolatileInterruptible blocker;privatefinalObject blockerLock =newObject();/* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code
*/voidblockedOn(Interruptible b){synchronized(blockerLock){
blocker = b;}}/**
* The minimum priority that a thread can have.
*/publicfinalstaticint MIN_PRIORITY =1;/**
* The default priority that is assigned to a thread.
*/publicfinalstaticint NORM_PRIORITY =5;/**
* The maximum priority that a thread can have.
*/publicfinalstaticint MAX_PRIORITY =10;/**
* Returns a reference to the currently executing thread object.
*
* @return the currently executing thread.
*/publicstaticnativeThreadcurrentThread();publicstaticnativevoidyield();publicstaticnativevoidsleep(long millis)throwsInterruptedException;publicstaticvoidsleep(long millis,int nanos)throwsInterruptedException{if(millis <0){thrownewIllegalArgumentException("timeout value is negative");}if(nanos <0|| nanos >999999){thrownewIllegalArgumentException("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)
*/privatevoidinit(ThreadGroup g,Runnable target,String name,long stackSize){init(g, target, name, stackSize,null,true);}privatevoidinit(ThreadGroup g,Runnable target,String name,long stackSize,AccessControlContext acc,boolean inheritThreadLocals){if(name ==null){thrownewNullPointerException("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();elsethis.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();}@OverrideprotectedObjectclone()throwsCloneNotSupportedException{thrownewCloneNotSupportedException();}publicThread(){init(null,null,"Thread-"+nextThreadNum(),0);}publicThread(Runnable target){init(null, target,"Thread-"+nextThreadNum(),0);}/**
* Creates a new Thread that inherits the given AccessControlContext.
* This is not a public constructor.
*/Thread(Runnable target,AccessControlContext acc){init(null, target,"Thread-"+nextThreadNum(),0, acc,false);}publicThread(ThreadGroup group,Runnable target){init(group, target,"Thread-"+nextThreadNum(),0);}publicThread(String name){init(null,null, name,0);}publicThread(ThreadGroup group,String name){init(group,null, name,0);}publicThread(Runnable target,String name){init(null, target, name,0);}publicThread(ThreadGroup group,Runnable target,String name){init(group, target, name,0);}publicThread(ThreadGroup group,Runnable target,String name,long stackSize){init(group, target, name, stackSize);}publicsynchronizedvoidstart(){/**
* 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)thrownewIllegalThreadStateException();/* 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 */}}}privatenativevoidstart0();@Overridepublicvoidrun(){if(target !=null){
target.run();}}/**
* This method is called by the system to give a Thread
* a chance to clean up before it actually exits.
*/privatevoidexit(){if(group !=null){
group.threadTerminated(this);
group =null;}/* Aggressively null out all reference fields: see bug 4006245 */
target =null;/* Speed the release of some of these resources */
threadLocals =null;
inheritableThreadLocals =null;
inheritedAccessControlContext =null;
blocker =null;
uncaughtExceptionHandler =null;}@Deprecatedpublicfinalvoidstop(){SecurityManager security =System.getSecurityManager();if(security !=null){checkAccess();if(this!=Thread.currentThread()){
security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);}}// A zero status value corresponds to "NEW", it can't change to// not-NEW because we hold the lock.if(threadStatus !=0){resume();// Wake up thread if it was suspended; no-op otherwise}// The VM can handle all thread statesstop0(newThreadDeath());}@Deprecatedpublicfinalsynchronizedvoidstop(Throwable obj){thrownewUnsupportedOperationException();}publicvoidinterrupt(){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();}publicstaticbooleaninterrupted(){returncurrentThread().isInterrupted(true);}publicbooleanisInterrupted(){returnisInterrupted(false);}/**
* Tests if some Thread has been interrupted. The interrupted state
* is reset or not based on the value of ClearInterrupted that is
* passed.
*/privatenativebooleanisInterrupted(booleanClearInterrupted);@Deprecatedpublicvoiddestroy(){thrownewNoSuchMethodError();}publicfinalnativebooleanisAlive();@Deprecatedpublicfinalvoidsuspend(){checkAccess();suspend0();}@Deprecatedpublicfinalvoidresume(){checkAccess();resume0();}publicfinalvoidsetPriority(int newPriority){ThreadGroup g;checkAccess();if(newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY){thrownewIllegalArgumentException();}if((g =getThreadGroup())!=null){if(newPriority > g.getMaxPriority()){
newPriority = g.getMaxPriority();}setPriority0(priority = newPriority);}}/**
* Returns this thread's priority.
*
* @return this thread's priority.
* @see #setPriority
*/publicfinalintgetPriority(){return priority;}publicfinalsynchronizedvoidsetName(String name){checkAccess();if(name ==null){thrownewNullPointerException("name cannot be null");}this.name = name;if(threadStatus !=0){setNativeName(name);}}/**
* Returns this thread's name.
*
* @return this thread's name.
* @see #setName(String)
*/publicfinalStringgetName(){return name;}publicstaticintactiveCount(){returncurrentThread().getThreadGroup().activeCount();}publicstaticintenumerate(Thread tarray[]){returncurrentThread().getThreadGroup().enumerate(tarray);}@DeprecatedpublicnativeintcountStackFrames();publicfinalsynchronizedvoidjoin(long millis)throwsInterruptedException{long base =System.currentTimeMillis();long now =0;if(millis <0){thrownewIllegalArgumentException("timeout value is negative");}if(millis ==0){while(isAlive()){wait(0);}}else{while(isAlive()){long delay = millis - now;if(delay <=0){break;}wait(delay);
now =System.currentTimeMillis()- base;}}}publicfinalsynchronizedvoidjoin(long millis,int nanos)throwsInterruptedException{if(millis <0){thrownewIllegalArgumentException("timeout value is negative");}if(nanos <0|| nanos >999999){thrownewIllegalArgumentException("nanosecond timeout value out of range");}if(nanos >=500000||(nanos !=0&& millis ==0)){
millis++;}join(millis);}publicfinalvoidjoin()throwsInterruptedException{join(0);}publicstaticvoiddumpStack(){newException("Stack trace").printStackTrace();}publicfinalvoidsetDaemon(boolean on){checkAccess();if(isAlive()){thrownewIllegalThreadStateException();}
daemon = on;}publicfinalbooleanisDaemon(){return daemon;}publicfinalvoidcheckAccess(){SecurityManager security =System.getSecurityManager();if(security !=null){
security.checkAccess(this);}}/**
* Returns a string representation of this thread, including the
* thread's name, priority, and thread group.
*
* @return a string representation of this thread.
*/publicStringtoString(){ThreadGroup group =getThreadGroup();if(group !=null){return"Thread["+getName()+","+getPriority()+","+
group.getName()+"]";}else{return"Thread["+getName()+","+getPriority()+","+""+"]";}}@CallerSensitivepublicClassLoadergetContextClassLoader(){if(contextClassLoader ==null)returnnull;SecurityManager sm =System.getSecurityManager();if(sm !=null){ClassLoader.checkClassLoaderPermission(contextClassLoader,Reflection.getCallerClass());}return contextClassLoader;}publicvoidsetContextClassLoader(ClassLoader cl){SecurityManager sm =System.getSecurityManager();if(sm !=null){
sm.checkPermission(newRuntimePermission("setContextClassLoader"));}
contextClassLoader = cl;}publicstaticnativebooleanholdsLock(Object obj);privatestaticfinalStackTraceElement[] EMPTY_STACK_TRACE
=newStackTraceElement[0];publicStackTraceElement[]getStackTrace(){if(this!=Thread.currentThread()){// check for getStackTrace permissionSecurityManager security =System.getSecurityManager();if(security !=null){
security.checkPermission(SecurityConstants.GET_STACK_TRACE_PERMISSION);}// optimization so we do not call into the vm for threads that// have not yet started or have terminatedif(!isAlive()){return EMPTY_STACK_TRACE;}StackTraceElement[][] stackTraceArray =dumpThreads(newThread[]{this});StackTraceElement[] stackTrace = stackTraceArray[0];// a thread that was alive during the previous isAlive call may have// since terminated, therefore not having a stacktrace.if(stackTrace ==null){
stackTrace = EMPTY_STACK_TRACE;}return stackTrace;}else{// Don't need JVM help for current threadreturn(newException()).getStackTrace();}}publicstaticMap<Thread,StackTraceElement[]>getAllStackTraces(){// check for getStackTrace permissionSecurityManager security =System.getSecurityManager();if(security !=null){
security.checkPermission(SecurityConstants.GET_STACK_TRACE_PERMISSION);
security.checkPermission(SecurityConstants.MODIFY_THREADGROUP_PERMISSION);}// Get a snapshot of the list of all threadsThread[] threads =getThreads();StackTraceElement[][] traces =dumpThreads(threads);Map<Thread,StackTraceElement[]> m =newHashMap<>(threads.length);for(int i =0; i < threads.length; i++){StackTraceElement[] stackTrace = traces[i];if(stackTrace !=null){
m.put(threads[i], stackTrace);}// else terminated so we don't put it in the map}return m;}privatestaticfinalRuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION =newRuntimePermission("enableContextClassLoaderOverride");/** cache of subclass security audit results *//* Replace with ConcurrentReferenceHashMap when/if it appears in a future
* release */privatestaticclassCaches{/** cache of subclass security audit results */staticfinalConcurrentMap<WeakClassKey,Boolean> subclassAudits =newConcurrentHashMap<>();/** queue for WeakReferences to audited subclasses */staticfinalReferenceQueue<Class<?>> subclassAuditsQueue =newReferenceQueue<>();}privatestaticbooleanisCCLOverridden(Class<?> cl){if(cl ==Thread.class)returnfalse;processQueue(Caches.subclassAuditsQueue,Caches.subclassAudits);WeakClassKey key =newWeakClassKey(cl,Caches.subclassAuditsQueue);Boolean result =Caches.subclassAudits.get(key);if(result ==null){
result =Boolean.valueOf(auditSubclass(cl));Caches.subclassAudits.putIfAbsent(key, result);}return result.booleanValue();}privatestaticbooleanauditSubclass(finalClass<?> subcl){Boolean result =AccessController.doPrivileged(newPrivilegedAction<Boolean>(){publicBooleanrun(){for(Class<?> cl = subcl;
cl !=Thread.class;
cl = cl.getSuperclass()){try{
cl.getDeclaredMethod("getContextClassLoader",newClass<?>[0]);returnBoolean.TRUE;}catch(NoSuchMethodException ex){}try{Class<?>[] params ={ClassLoader.class};
cl.getDeclaredMethod("setContextClassLoader", params);returnBoolean.TRUE;}catch(NoSuchMethodException ex){}}returnBoolean.FALSE;}});return result.booleanValue();}privatenativestaticStackTraceElement[][]dumpThreads(Thread[] threads);privatenativestaticThread[]getThreads();publiclonggetId(){return tid;}publicenumState{
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;}publicStategetState(){// get current thread statereturn sun.misc.VM.toThreadState(threadStatus);}@FunctionalInterfacepublicinterfaceUncaughtExceptionHandler{/**
* Method invoked when the given thread terminates due to the
* given uncaught exception.
* <p>Any exception thrown by this method will be ignored by the
* Java Virtual Machine.
* @param t the thread
* @param e the exception
*/voiduncaughtException(Thread t,Throwable e);}// null unless explicitly setprivatevolatileUncaughtExceptionHandler uncaughtExceptionHandler;// null unless explicitly setprivatestaticvolatileUncaughtExceptionHandler defaultUncaughtExceptionHandler;publicstaticvoidsetDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh){SecurityManager sm =System.getSecurityManager();if(sm !=null){
sm.checkPermission(newRuntimePermission("setDefaultUncaughtExceptionHandler"));}
defaultUncaughtExceptionHandler = eh;}publicstaticUncaughtExceptionHandlergetDefaultUncaughtExceptionHandler(){return defaultUncaughtExceptionHandler;}publicUncaughtExceptionHandlergetUncaughtExceptionHandler(){return uncaughtExceptionHandler !=null?
uncaughtExceptionHandler : group;}publicvoidsetUncaughtExceptionHandler(UncaughtExceptionHandler eh){checkAccess();
uncaughtExceptionHandler = eh;}/**
* Dispatch an uncaught exception to the handler. This method is
* intended to be called only by the JVM.
*/privatevoiddispatchUncaughtException(Throwable e){getUncaughtExceptionHandler().uncaughtException(this, e);}/**
* Removes from the specified map any keys that have been enqueued
* on the specified reference queue.
*/staticvoidprocessQueue(ReferenceQueue<Class<?>> queue,ConcurrentMap<?extendsWeakReference<Class<?>>,?> map){Reference<?extendsClass<?>> ref;while((ref = queue.poll())!=null){
map.remove(ref);}}/**
* Weak key for Class objects.
**/staticclassWeakClassKeyextendsWeakReference<Class<?>>{/**
* saved value of the referent's identity hash code, to maintain
* a consistent hash code after the referent has been cleared
*/privatefinalint hash;/**
* Create a new WeakClassKey to the given object, registered
* with a queue.
*/WeakClassKey(Class<?> cl,ReferenceQueue<Class<?>> refQueue){super(cl, refQueue);
hash =System.identityHashCode(cl);}/**
* Returns the identity hash code of the original referent.
*/@OverridepublicinthashCode(){return hash;}/**
* Returns true if the given object is this identical
* WeakClassKey instance, or, if this object's referent has not
* been cleared, if the given object is another WeakClassKey
* instance with the identical non-null referent as this one.
*/@Overridepublicbooleanequals(Object obj){if(obj ==this)returntrue;if(obj instanceofWeakClassKey){Object referent =get();return(referent !=null)&&(referent ==((WeakClassKey) obj).get());}else{returnfalse;}}}// The following three initially uninitialized fields are exclusively// managed by class java.util.concurrent.ThreadLocalRandom. These// fields are used to build the high-performance PRNGs in the// concurrent code, and we can not risk accidental false sharing.// Hence, the fields are isolated with @Contended./** The current seed for a ThreadLocalRandom */@sun.misc.Contended("tlr")long threadLocalRandomSeed;/** Probe hash value; nonzero if threadLocalRandomSeed initialized */@sun.misc.Contended("tlr")int threadLocalRandomProbe;/** Secondary seed isolated from public ThreadLocalRandom sequence */@sun.misc.Contended("tlr")int threadLocalRandomSecondarySeed;/* Some private helper methods */privatenativevoidsetPriority0(int newPriority);privatenativevoidstop0(Object o);privatenativevoidsuspend0();privatenativevoidresume0();privatenativevoidinterrupt0();privatenativevoidsetNativeName(String name);}
5 ThreadPool
5.1 Executor接口
packagejava.util.concurrent;/**
* ...
* @since 1.5
* @author Doug Lea
*/publicinterfaceExecutor{/**
* Executes the given command at some time in the future. The command
* may execute in a new thread, in a pooled thread, or in the calling
* thread, at the discretion of the {@code Executor} implementation.
*
* @param command the runnable task
* @throws RejectedExecutionException if this task cannot be
* accepted for execution
* @throws NullPointerException if command is null
*/voidexecute(Runnable command);}