Thread類【JDK源碼分析】
- 前言
- 推薦
- 說明
- Thread類
- 基本資訊
- 嵌套類摘要
- 字段摘要
- 方法摘要
- currentThread
- yield
- sleep
- sleep
- start
- start0
- run
- Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?翻譯
- stop
- interrupt
- interrupted
- isInterrupted
- destroy
- suspend
- resume
- join
- join
- join
- GetterSetter
- 測試
- 附:Thread源碼
- 總結
- 最後
前言
2022/10/25
路漫漫其修遠兮,吾将上下而求索
本文是根據jdk學習所做筆記
僅供學習交流使用,轉載注明出處
推薦
JDK API 1.6 中文版
說明
以下内容是結合很多資料進行編寫的
源碼為jdk1.8的
斜體樣式 為自己的思考
下劃線為自己所畫的重點
Thread類
基本資訊
java.lang
類 Thread
java.lang.Object
繼承者 java.lang.Thread
所有已實作的接口:
Runnable
public class Thread
extends Object
implements Runnable
線程 是程式中的執行線程。Java 虛拟機允許應用程式并發地運作多個執行線程。
每個線程都有一個優先級,高優先級線程的執行優先于低優先級線程。每個線程都可以或不可以标記為一個守護程式。當某個線程中運作的代碼建立一個新 Thread 對象時,該新線程的初始優先級被設定為建立線程的優先級,并且當且僅當建立線程是守護線程時,新線程才是守護程式。
當 Java 虛拟機啟動時,通常都會有單個非守護線程(它通常會調用某個指定類的 main 方法)。Java 虛拟機會繼續執行線程,直到下列任一情況出現時為止:
- 調用了 Runtime 類的 exit 方法,并且安全管理器允許退出操作發生。
- 非守護線程的所有線程都已停止運作,無論是通過從對 run 方法的調用中傳回,還是通過抛出一個傳播到 run 方法之外的異常。
建立新執行線程有兩種方法。一種方法是将類聲明為 Thread 的子類。該子類應重寫 Thread 類的 run 方法。接下來可以配置設定并啟動該子類的執行個體。例如,計算大于某一規定值的質數的線程可以寫成:
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
然後,下列代碼會建立并啟動一個線程:
PrimeThread p = new PrimeThread(143);
p.start();
建立線程的另一種方法是聲明實作 Runnable 接口的類。該類然後實作 run 方法。然後可以配置設定該類的執行個體,在建立 Thread 時作為一個參數來傳遞并啟動。采用這種風格的同一個例子如下所示:
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
然後,下列代碼會建立并啟動一個線程:
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
每個線程都有一個辨別名,多個線程可以同名。如果線程建立時沒有指定辨別名,就會為其生成一個新名稱。
從以下版本開始:
JDK1.0
另請參見:
Runnable, Runtime.exit(int), run(), stop()
嵌套類摘要
static class
Thread.State
線程狀态。
java.lang
枚舉 Thread.State
java.lang.Object
繼承者 java.lang.Enum<Thread.State>
繼承者 java.lang.Thread.State
所有已實作的接口:
Serializable, Comparable<Thread.State>
正在封閉類:
Thread
public static enum Thread.Stateextends Enum<Thread.State>線程狀态。線程可以處于下列狀态之一:
NEW
至今尚未啟動的線程處于這種狀态。
RUNNABLE
正在 Java 虛拟機中執行的線程處于這種狀态。
BLOCKED
受阻塞并等待某個螢幕鎖的線程處于這種狀态。
WAITING
無限期地等待另一個線程來執行某一特定操作的線程處于這種狀态。
TIMED_WAITING
等待另一個線程來執行取決于指定等待時間的操作的線程處于這種狀态。
TERMINATED
已退出的線程處于這種狀态。
在給定時間點上,一個線程隻能處于一種狀态。這些狀态是虛拟機狀态,它們并沒有反映所有作業系統線程狀态。
public enum State {
/**
* Thread state for a thread which has not yet started.
*/
NEW,
/**
* 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,
/**
* 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,
/**
* 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 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;
}
/**
* Returns the state of this thread.
* This method is designed for use in monitoring of the system state,
* not for synchronization control.
*
* @return this thread's state.
* @since 1.5
*/
public State getState() {
// get current thread state
return sun.misc.VM.toThreadState(threadStatus);
}
static interface
Thread.UncaughtExceptionHandler
當 Thread 因未捕獲的異常而突然終止時,調用處理程式的接口。
java.lang
接口 Thread.UncaughtExceptionHandler
所有已知實作類:
ThreadGroup
正在封閉類:
Thread
public static interface Thread.UncaughtExceptionHandler當 Thread 因未捕獲的異常而突然終止時,調用處理程式的接口。
當某一線程因未捕獲的異常而即将終止時,Java 虛拟機将使用 Thread.getUncaughtExceptionHandler() 查詢該線程以獲得其 UncaughtExceptionHandler 的線程,并調用處理程式的 uncaughtException 方法,将線程和異常作為參數傳遞。如果某一線程沒有明确設定其 UncaughtExceptionHandler,則将它的 ThreadGroup 對象作為其 UncaughtExceptionHandler。如果 ThreadGroup 對象對處理異常沒有什麼特殊要求,那麼它可以将調用轉發給預設的未捕獲異常處理程式。
從以下版本開始:
1.5
另請參見:
Thread.setDefaultUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler), Thread.setUncaughtExceptionHandler
(java.lang.Thread.UncaughtExceptionHandler), ThreadGroup.uncaughtException(java.lang.Thread, java.lang.Throwable)
// Added in JSR-166
/**
* Interface for handlers invoked when a <tt>Thread</tt> abruptly
* terminates due to an uncaught exception.
* <p>When a thread is about to terminate due to an uncaught exception
* the Java Virtual Machine will query the thread for its
* <tt>UncaughtExceptionHandler</tt> using
* {@link #getUncaughtExceptionHandler} and will invoke the handler's
* <tt>uncaughtException</tt> method, passing the thread and the
* exception as arguments.
* If a thread has not had its <tt>UncaughtExceptionHandler</tt>
* explicitly set, then its <tt>ThreadGroup</tt> object acts as its
* <tt>UncaughtExceptionHandler</tt>. If the <tt>ThreadGroup</tt> object
* has no
* special requirements for dealing with the exception, it can forward
* the invocation to the {@linkplain #getDefaultUncaughtExceptionHandler
* default uncaught exception handler}.
*
* @see #setDefaultUncaughtExceptionHandler
* @see #setUncaughtExceptionHandler
* @see ThreadGroup#uncaughtException
* @since 1.5
*/
@FunctionalInterface
public interface UncaughtExceptionHandler {
/**
* 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
*/
void uncaughtException(Thread t, Throwable e);
}
字段摘要
static int MAX_PRIORITY
線程可以具有的最高優先級。
static int MIN_PRIORITY
線程可以具有的最低優先級。
static int NORM_PRIORITY
配置設定給線程的預設優先級。
/**
* The minimum priority that a thread can have.
*/
public final static int MIN_PRIORITY = 1;
/**
* The default priority that is assigned to a thread.
*/
public final static int NORM_PRIORITY = 5;
/**
* The maximum priority that a thread can have.
*/
public final static int MAX_PRIORITY = 10;
方法摘要
currentThread
public static Thread currentThread()
傳回對目前正在執行的線程對象的引用。
傳回:
目前執行的線程。
/**
* Returns a reference to the currently executing thread object.
*
* @return the currently executing thread.
*/
public static native Thread currentThread();
yield
public static void 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();
sleep
public static void sleep(long millis)
throws InterruptedException
在指定的毫秒數内讓目前正在執行的線程休眠(暫停執行),此操作受到系統計時器和排程程式精度和準确性的影響。該線程不丢失任何螢幕的所屬權。
參數:
millis - 以毫秒為機關的休眠時間。
抛出:
InterruptedException - 如果任何線程中斷了目前線程。當抛出該異常時,目前線程的中斷狀态 被清除。
另請參見:
Object.notify()
/**
* 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;
sleep
public static void sleep(long millis,
int nanos)
throws InterruptedException
在指定的毫秒數加指定的納秒數内讓目前正在執行的線程休眠(暫停執行),此操作受到系統計時器和排程程式精度和準确性的影響。該線程不丢失任何螢幕的所屬權。
參數:
millis - 以毫秒為機關的休眠時間。
nanos - 要休眠的另外 0-999999 納秒。
抛出:
IllegalArgumentException - 如果 millis 值為負或 nanos 值不在 0-999999 範圍内。
InterruptedException - 如果任何線程中斷了目前線程。當抛出該異常時,目前線程的中斷狀态 被清除。
另請參見:
Object.notify()
/**
* 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);
}
start
public void start()
使該線程開始執行;Java 虛拟機調用該線程的 run 方法。
結果是兩個線程并發地運作;目前線程(從調用傳回給 start 方法)和另一個線程(執行其 run 方法)。
多次啟動一個線程是非法的。特别是當線程已經結束執行後,不能再重新啟動。
抛出:
IllegalThreadStateException - 如果線程已經啟動。
另請參見:
run(), stop()
/**
* 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() {
/**
* 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 */
}
}
}
start0
native方法
java不是真正意義上的建立線程
private native void start0();
run
public void run()
如果該線程是使用獨立的 Runnable 運作對象構造的,則調用該 Runnable 對象的 run 方法;否則,該方法不執行任何操作并傳回。
Thread 的子類應該重寫該方法。
指定者:
接口 Runnable 中的 run
另請參見:
start(), stop(), Thread(ThreadGroup, Runnable, String)
/**
* 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();
}
}
Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?翻譯
Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?翻譯
stop
@Deprecated
public final void stop()已過時。
該方法具有固有的不安全性。用 Thread.stop 來終止線程将釋放它已經鎖定的所有螢幕(作為沿堆棧向上傳播的未檢查 ThreadDeath 異常的一個自然後果)。如果以前受這些螢幕保護的任何對象都處于一種不一緻的狀态,則損壞的對象将對其他線程可見,這有可能導緻任意的行為。stop 的許多使用都應由隻修改某些變量以訓示目标線程應該停止運作的代碼來取代。目标線程應定期檢查該變量,并且如果該變量訓示它要停止運作,則從其運作方法依次傳回。如果目标線程等待很長時間(例如基于一個條件變量),則應使用 interrupt 方法來中斷該等待。有關更多資訊,請參閱為何不贊成使用 Thread.stop、Thread.suspend 和 Thread.resume?。
強迫線程停止執行。
如果安裝了安全管理器,則以 this 作為其參數調用 checkAccess 方法。這可能引發 SecurityException(在目前線程中)。
如果該線程不同于目前線程(即目前線程試圖終止除它本身以外的某一線程),則安全管理器的 checkPermission 方法(帶有 RuntimePermission(“stopThread”) 參數)也會被調用。這會再次抛出 SecurityException(在目前線程中)。
無論該線程在做些什麼,它所代表的線程都被迫異常停止,并抛出一個新建立的 ThreadDeath 對象,作為異常。
停止一個尚未啟動的線程是允許的。如果最後啟動了該線程,它會立即終止。
應用程式通常不應試圖捕獲 ThreadDeath,除非它必須執行某些異常的清除操作(注意,抛出 ThreadDeath 将導緻 try 語句的 finally 子句線上程正式終止前執行)。如果 catch 子句捕獲了一個 ThreadDeath 對象,則重新抛出該對象很重要,因為這樣該線程才會真正終止。
對其他未捕獲的異常作出反應的頂級錯誤處理程式不會列印輸出消息,或者另外通知應用程式未捕獲到的異常是否為 ThreadDeath 的一個執行個體。
抛出:
SecurityException - 如果目前線程不能修改該線程。
另請參見:
interrupt(), checkAccess(), run(), start(), ThreadDeath, ThreadGroup.uncaughtException(Thread,Throwable), SecurityManager.checkAccess(Thread), SecurityManager.checkPermission(java.security.Permission)
interrupt
public void interrupt()中斷線程。
如果目前線程沒有中斷它自己(這在任何情況下都是允許的),則該線程的 checkAccess 方法就會被調用,這可能抛出 SecurityException。
如果線程在調用 Object 類的 wait()、wait(long) 或 wait(long, int) 方法,或者該類的 join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法過程中受阻,則其中斷狀态将被清除,它還将收到一個 InterruptedException。
如果該線程在可中斷的通道上的 I/O 操作中受阻,則該通道将被關閉,該線程的中斷狀态将被設定并且該線程将收到一個 ClosedByInterruptException。
如果該線程在一個 Selector 中受阻,則該線程的中斷狀态将被設定,它将立即從選擇操作傳回,并可能帶有一個非零值,就好像調用了選擇器的 wakeup 方法一樣。
如果以前的條件都沒有儲存,則該線程的中斷狀态将被設定。
中斷一個不處于活動狀态的線程不需要任何作用。
抛出:
SecurityException - 如果目前線程無法修改該線程
/**
* 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.
*
* <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}.
*
* <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}.
*
* <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();
}
interrupted
public static boolean interrupted()測試目前線程是否已經中斷。線程的中斷狀态 由該方法清除。換句話說,如果連續兩次調用該方法,則第二次調用将傳回 false(在第一次調用已清除了其中斷狀态之後,且第二次調用檢驗完中斷狀态前,目前線程再次中斷的情況除外)。
線程中斷被忽略,因為在中斷時不處于活動狀态的線程将由此傳回 false 的方法反映出來。
傳回:
如果目前線程已經中斷,則傳回 true;否則傳回 false。
另請參見:
isInterrupted()
isInterrupted
public boolean isInterrupted()測試線程是否已經中斷。線程的中斷狀态 不受該方法的影響。
線程中斷被忽略,因為在中斷時不處于活動狀态的線程将由此傳回 false 的方法反映出來。
傳回:
如果該線程已經中斷,則傳回 true;否則傳回 false。
另請參見:
interrupted()
destroy
@Deprecated
public void destroy()已過時。 該方法最初用于破壞該線程,但不作任何清除。它所保持的任何螢幕都會保持鎖定狀态。不過,該方法決不會被實作。即使要實作,它也極有可能以 suspend() 方式被死鎖。如果目标線程被破壞時保持一個保護關鍵系統資源的鎖,則任何線程在任何時候都無法再次通路該資源。如果另一個線程曾試圖鎖定該資源,則會出現死鎖。這類死鎖通常會證明它們自己是“當機”的程序。有關更多資訊,請參閱為何不贊成使用 Thread.stop、Thread.suspend 和 Thread.resume?。
抛出 NoSuchMethodError。
抛出:
NoSuchMethodError - 始終
isAlive
public final boolean isAlive()測試線程是否處于活動狀态。如果線程已經啟動且尚未終止,則為活動狀态。
傳回:
如果該線程處于活動狀态,則傳回 true;否則傳回 false。
suspend
@Deprecated
public final void suspend()已過時。 該方法已經遭到反對,因為它具有固有的死鎖傾向。如果目标線程挂起時在保護關鍵系統資源的螢幕上保持有鎖,則在目标線程重新開始以前任何線程都不能通路該資源。如果重新開始目标線程的線程想在調用 resume 之前鎖定該螢幕,則會發生死鎖。這類死鎖通常會證明自己是“當機”的程序。有關更多資訊,請參閱為何不贊成使用 Thread.stop、Thread.suspend 和 Thread.resume?。
挂起線程。
首先,調用線程的 checkAccess 方法,且不帶任何參數。這可能抛出 SecurityException(在目前線程中)。
如果線程處于活動狀态則被挂起,且不再有進一步的活動,除非重新開始。
抛出:
SecurityException - 如果目前線程不能修改該線程。
另請參見:
checkAccess()
resume
@Deprecated
public final void resume()已過時。 該方法隻與 suspend() 一起使用,但 suspend() 已經遭到反對,因為它具有死鎖傾向。有關更多資訊,請參閱為何不贊成使用 Thread.stop、Thread.suspend 和 Thread.resume?。
重新開始挂起的程序。
首先,調用線程的 checkAccess 方法,且不帶任何參數。這可能抛出 SecurityException(在目前線程中)。
如果線程處于活動狀态但被挂起,則它會在執行過程中重新開始并允許繼續活動。
抛出:
SecurityException - 如果目前線程不能修改該線程。
另請參見:
checkAccess(), suspend()
join
public final void join(long millis)
throws InterruptedException等待該線程終止的時間最長為 millis 毫秒。逾時為 0 意味着要一直等下去。
參數:
millis - 以毫秒為機關的等待時間。
抛出:
InterruptedException - 如果任何線程中斷了目前線程。當抛出該異常時,目前線程的中斷狀态 被清除。
join
public final void join(long millis)
throws InterruptedException
等待該線程終止的時間最長為 millis 毫秒。逾時為 0 意味着要一直等下去。
參數:
millis - 以毫秒為機關的等待時間。
抛出:
InterruptedException - 如果任何線程中斷了目前線程。當抛出該異常時,目前線程的中斷狀态 被清除。
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()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
join
public final void join(long millis,
int nanos)
throws InterruptedException
等待該線程終止的時間最長為 millis 毫秒 + nanos 納秒。
參數:
millis - 以毫秒為機關的等待時間。
nanos - 要等待的 0-999999 附加納秒。
抛出:
IllegalArgumentException - 如果 millis 值為負,則 nanos 的值不在 0-999999 範圍内。
InterruptedException - 如果任何線程中斷了目前線程。當抛出該異常時,目前線程的中斷狀态 被清除。
/**
* Waits at most {@code millis} milliseconds plus
* {@code nanos} nanoseconds for this thread to die.
*
* <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
*
* @param nanos
* {@code 0-999999} additional nanoseconds to wait
*
* @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 final synchronized void join(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++;
}
join(millis);
}
join
public final void join()
throws InterruptedException
等待該線程終止。
抛出:
InterruptedException - 如果任何線程中斷了目前線程。當抛出該異常時,目前線程的中斷狀态 被清除。
/**
* Waits for this thread to die.
*
* <p> An invocation of this method behaves in exactly the same
* way as the invocation
*
* <blockquote>
* {@linkplain #join(long) join}{@code (0)}
* </blockquote>
*
* @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 void join() throws InterruptedException {
join(0);
}
GetterSetter
private volatile 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 volatile int threadStatus = 0;
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();
測試
package testlang;
/**
* @author CSDN@日星月雲
* @date 2022/10/25 18:48
*/
public class TestThread {
public static void main(String[] args) {
//方式一:繼承Thread
PrimeThread p = new PrimeThread(143);
p.start();
//方式二:實作Runnable
PrimeRun p1 = new PrimeRun(143);
new Thread(p1).start();
}
}
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
System.out.println(minPrime);
}
}
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
System.out.println(minPrime);
}
}
附:Thread源碼
package java.lang;
/**
* 作業系統在運作一個程式時,會為其建立一個程序,一個程序中可以建立多個線程, 這些線程都擁有各自的計數器,堆棧和局部變量等屬性,
* 并且可以通路共享的記憶體變量, 處理器根據時間片算法線上程之間進行高速切換,在宏觀上給人以線程同時執行的感覺.
*
* 每個線程都有相應的優先級,從1到10,預設優先級為5,高優先級的線程獲得CPU時間片優勢大于低優先級的, 但是不是絕對,很多作業系統以及JVM版本并不認可線程的優先級的說法
*
* 每個線程都可以被設定為守護線程(Daemon),設定時線上程啟動前設定,調用Thread.setDaemon(true),守護線程
* 主要用于程式中背景排程以及支援性工作.當JVM中不存在Daemon線程時,JVM會退出,是以Daemon線程中的finally中的代碼 不一定會執行
*
* 建立線程一般有兩種方法: 內建Thread類,實作Runnable接口 實際上Thread也是實作Runable接口
*/
public class Thread implements Runnable {
/** static修飾,確定本地注冊建立線程時執行,native修飾,調用其他語言的方法 */
private static native void registerNatives();
static {
registerNatives();
}
private volatile char name[]; // 線程名,可以修改且對線程可見
private int priority; // 線程優先級,1到10,預設為5
private Thread threadQ;
private long eetop;
/* 是否是單步執行*/
private boolean single_step;
/* 該線程是否是守護線程 */
private boolean daemon = false;
/* JVM 狀态 */
private boolean stillborn = false;
/* 要被執行的run方法 */
private Runnable target;
/* 線程所屬線程組 */
private ThreadGroup group;
/* 線程的類加載器 */
private ClassLoader contextClassLoader;
/* 該線程繼承的通路控制上下文 */
private AccessControlContext inheritedAccessControlContext;
/* 用于自動編号的匿名線程 ,預設線程編号*/
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
/* 該線程的本地變量值,此map由ThreadLocal類進行維護,是一個維護線程本地變量的hashmap,hashmap的key為弱引用,可以增長對象的存活時間*/
ThreadLocal.ThreadLocalMap threadLocals = null;
/*該線程繼承所得到本地變量值,此map由inheritableThreadLocals類維護*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
/*棧的深度,預設為0,此數字如何被使用完全取決于虛拟機自己;也有一些虛拟機會忽略此變量值.*/
private long stackSize;
/*本地線程終止後,JVM私有的一個狀态值*/
private long nativeParkEventPointer;
/* 線程id*/
private long tid;
/* 用于生成線程Id */
private static long threadSeqNumber;
/* 為工具提供的線程狀态值,初始化值辨別目前線程還未運作*/
private volatile int threadStatus = 0;
/* 擷取下一個線程id*/
private static synchronized long nextThreadID() {
return ++threadSeqNumber;
}
/* 線程共享變量d*/
volatile Object parkBlocker;
/* 阻塞變量,如果線程的中斷狀态被設定,則應該調用此線程阻塞對象的中斷方法*/
private volatile Interruptible blocker;
private final Object blockerLock = new Object();
/* 設定block的值,*/
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;
/* 傳回目前正在執行線程對象的應用,這是一個native修飾的方法*/
public static native Thread currentThread();
/**
* 提示線程排程器目前線程放棄CPU的使用,當然線程排程器可以忽略,
* 讓出CPU是一種啟發式嘗試,已改善線程之間的相對發展,否者将會過度利用CPU或者是其他線程獲得不了CPU執行權限
*/
public static native void yield();
/* 睡眠millis毫秒數, 此方法的調用不會引起目前線程放棄任何監聽器的所有權*/
public static native void sleep(long millis) throws InterruptedException;
/* 睡眠millis毫秒數,nanos納秒數,,此方法的調用不會引起目前線程放棄任何監聽器的所有權*/
public static void sleep(long millis, int nanos) throws InterruptedException {
// 毫秒值小于0,不合法
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
// 納秒小于0 或者大于等于100萬(1秒),納秒不合法
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException("nanosecond timeout value out of range");
}
// 納秒大于等于50萬,或者有納秒數,毫秒數為0,毫秒數加1
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
// 調用睡眠方法
sleep(millis);
}
/*利用目前通路控制上下文(AccessControlContext)來初始化一個線程*/
private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
init(g, target, name, stackSize, 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();
if (g == null) {
// 線程的組為空
if (security != null) {
// 線程的組為空,從系統安全管理器中獲得線程組
g = security.getThreadGroup();
}
//系統安全管理器為null,則使用目前執行線程的組
if (g == null) {
g = parent.getThreadGroup();
}
}
/* 檢查是否允許目前線程修改線程組的參數 */
g.checkAccess();
//是否受限通路
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
// 将線程組中的容器容量增加1
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);
//設定棧的深度
this.stackSize = stackSize;
//設定線程id
tid = nextThreadID();
}
/*重寫Object的克隆方法,但是線程不允許克隆.*/
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
/*無參構造,建立一個線程對象,線程組為安全管理器或者父線程的線程組,沒有執行方法,名字預設,棧深度為0*/
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
/*利用Runnable建立線程,有執行方法,其餘均是預設狀态,Runnable中有run方法*/
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
/*利用Runnable建立線程,傳入繼承通路控制上下文*/
Thread(Runnable target, AccessControlContext acc) {
init(null, target, "Thread-" + nextThreadNum(), 0, acc);
}
/* 傳入線程組以及Rannable構造*/
public Thread(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);
}
/* 傳入線程名構造*/
public Thread(String name) {
init(null, null, name, 0);
}
/* 傳入線程組以及線程名構造*/
public Thread(ThreadGroup group, String name) {
init(group, null, name, 0);
}
/* 傳入Runnable對象以及線程名構造*/
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
/* 傳入線程組,Runnable對象,線程名構造*/
public Thread(ThreadGroup group, Runnable target, String name) {
init(group, target, name, 0);
}
/* 傳入線程組,Runnable對象,線程名構,棧的深度*/
public Thread(ThreadGroup group, Runnable target, String name, long stackSize) {
init(group, target, name, stackSize);
}
/**
* 線程啟動方法
* 此方法的調用會引起目前線程的執行;JVM會調用此線程的run()方法,
* 并不會被主要方法線程or由虛拟機建立的系統組線程所調用
* 任何向此方法添加的新功能方法在未來都會被添加到虛拟機中
* 結果就是兩個線程可以并發執行:目前線程(從調用的start方法傳回)和另一個線程(它在執行run方法).
* 一個線程可以被調用多次.
* 尤其注意:一個線程執行完成後可能并不會再被重新執行.
*/
public synchronized void start() {
//0狀态值代表了NEW的狀态.
if (threadStatus != 0)
// 不是新建立的狀态抛出異常
throw new IllegalThreadStateException();
// 向線程組裡添加此線程,注意:線程建立的時候隻是将線程組中的容器容量增加1
group.add(this);
boolean started = false;
try {
// 使線程進入可運作狀态(runnable)
start0();
started = true;
} finally {
try {
if (!started) {
// 啟動失敗,再線程組中删除改線程
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
}
}
}
/* 本地方法,使線程進入可運作狀态(就緒)*/
private native void start0();
/*線程獲得CPU執行權限後執行的方法,實際上是調用的Runnable中的run()*/
@Override
public void run() {
if (target != null) {
target.run();
}
}
/*這是在run方法執行結束後,此方法由系統調用,用于在一個線程退出前做一些掃尾工作.*/
private void exit() {
if (group != null) {
// 加鎖執行,删除該線程
group.threadTerminated(this);
group = null;
}
// GC 回收,全部置為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;
}
/*停止方法,已過期,有風險,不建議使用*/
@Deprecated
public final void stop() {
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 states
stop0(new ThreadDeath());
}
/*停止方法,已過期,有風險,不建議使用*/
@Deprecated
public final synchronized void stop(Throwable obj) {
throw new UnsupportedOperationException();
}
/**
* 中斷目前線程, 一般來說sleep(),join(),wait()在檢查到線程的中斷狀态的時候,
* 會抛出中斷異常InteruptedExeption,以及清除線程的中斷狀态
*/
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();
}
/**
* 判斷目前線程是否是中斷狀态,線程的中斷狀态會被此方法清除,
* 也就是如果此方法兩次調用都成功,那麼在第二次調用的傳回結果為false
* 除非在第一次調用完後和第二次調用前,目前線程被再次中斷
* 因為在中斷狀态被調用線程并處于alive狀态而忽略線程中斷的情況會由于此方法的調用而受影響
*/
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
/*判斷目前線程是夠是中斷狀态,線程的中斷狀态不會被此方法清除*/
public boolean isInterrupted() {
return isInterrupted(false);
}
/*本地方法,測試線程是否被中斷. 中斷狀态會被重置or并不依賴于之前的中斷清除的值.*/
private native boolean isInterrupted(boolean ClearInterrupted);
/*過期無用方法*/
@Deprecated
public void destroy() {
throw new NoSuchMethodError();
}
/*本地方法, 測試目前線程是否處于存活狀态,一個線程在死亡狀态前都是存活狀态*/
public final native boolean isAlive();
/* 過期方法*/
@Deprecated
public final void suspend() {
checkAccess();
suspend0();
}
/* 過期方法*/
@Deprecated
public final void resume() {
checkAccess();
resume0();
}
/* 設定目前線程的優先級,設定的優先級不能大于線程組的最大線程優先級*/
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);
}
}
/* 擷取線程的優先級*/
public final int getPriority() {
return priority;
}
/* 設定目前線程的名字,同步方法*/
public final synchronized void setName(String name) {
checkAccess();
this.name = name.toCharArray();
if (threadStatus != 0) {
setNativeName(name);
}
}
/* 擷取線程的名字*/
public final String getName() {
return new String(name, true);
}
/* 擷取線程的線程組*/
public final ThreadGroup getThreadGroup() {
return group;
}
/* 傳回線程所屬線程組的線程數,估值*/
public static int activeCount() {
return currentThread().getThreadGroup().activeCount();
}
/* 将目前線程組以及子組所有活着的線程拷貝到參數數組中*/
public static int enumerate(Thread tarray[]) {
return currentThread().getThreadGroup().enumerate(tarray);
}
/* 過期方法*/
@Deprecated
public native int countStackFrames();
/* 最多等待參數millis時長,目前線程就會死亡,參數為0時則需要繼續等待*/
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");
}
// 等待時長為0,繼續等待
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
/* 最多等待參數millis毫秒加nanos納秒時長,目前線程就會死亡,參數為0時則需要繼續等待*/
public final synchronized void join(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++;
}
join(millis);
}
/* 等待一直到線程死亡.*/
public final void join() throws InterruptedException {
join(0);
}
/* 此方法隻用于debug*/
public static void dumpStack() {
new Exception("Stack trace").printStackTrace();
}
/* 将目前線程設定為守護線程or使用者線程. 此方法在start前被調用.如果值為true,則此線程被設定為守護線程.*/
public final void setDaemon(boolean on) {
checkAccess();
if (isAlive()) {
throw new IllegalThreadStateException();
}
daemon = on;
}
/* 判斷線程是否為守護線程*/
public final boolean isDaemon() {
return daemon;
}
/**
* 确定目前運作的線程是否有權利更改此線程相關屬性. 如果有安全管理器,則會将目前線程作為參數傳入checkAccess()方法
* 這可能會導緻SecurityException異常的抛出
*/
public final void checkAccess() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkAccess(this);
}
}
/* 傳回線程基本資訊*/
public String toString() {
ThreadGroup group = getThreadGroup();
if (group != null) {
return "Thread[" + getName() + "," + getPriority() + "," + group.getName() + "]";
} else {
return "Thread[" + getName() + "," + getPriority() + "," + "" + "]";
}
}
/* 此方法傳回此線程的上下文類加載器.*/
@CallerSensitive
public ClassLoader getContextClassLoader() {
if (contextClassLoader == null)
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader.checkClassLoaderPermission(contextClassLoader, Reflection.getCallerClass());
}
return contextClassLoader;
}
/* 設定線程上下文類加載器*/
public void setContextClassLoader(ClassLoader cl) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("setContextClassLoader"));
}
contextClassLoader = cl;
}
/*當且僅當,目前線程持有指定對象的監聽器鎖時,傳回傳回true. 這一方法被設計的目的是:用于程式自身去聲明它已經有某個對象的鎖啦.*/
public static native boolean holdsLock(Object obj);
/* 空棧元素對象*/
private static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0];
/**
* 傳回表示該線程堆棧轉儲的堆棧跟蹤元素數組。 如果線程還沒有start,or雖然start了,但是并沒有被CPU調用過,or線程以及終止了,則傳回數組長度為0.
* 如果傳回數組長度非0,則數組中第一個元素(索引為0)代表了棧的頂部,就是所有調用方法中距離現在時間最近的那個.
* 數組的最後一個元素代表了棧的底部,這是所有調用方法中距離現在時間最遠的那個.
* 如果存在安全管理器,且這一線程又不是目前線程,則安全管理器的checkPermission()方法會被調用以檢視
* 一些虛拟機在某些情況下,可能會在棧跟蹤時遺漏至少一個以上的棧.在極端情況下,虛拟機沒有任何棧跟蹤資訊是以傳回數組長度為0.
*/
public StackTraceElement[] getStackTrace() {
if (this != Thread.currentThread()) {
// check for getStackTrace permission
SecurityManager 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 terminated
if (!isAlive()) {
return EMPTY_STACK_TRACE;
}
StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {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 thread
return (new Exception()).getStackTrace();
}
}
/**
* 傳回一個用于所有存活線程的棧跟蹤資訊的map. map的key是每個線程;value是對應線程的棧跟蹤元素的一個數組.
* 當此方法被調用時,可能有些線程正在執行.每一個線程的棧跟蹤資訊都代表了線程在某一時刻狀态的快照且每一個棧跟蹤資訊 會在不同的時間得到.
* 如果虛拟機中某一個線程沒有棧跟蹤資訊則其數組長度為0.
* 如果有安全管理器,則安全管理器的checkPermission方法會被調用以檢查是否允許擷取所有線程的棧跟蹤資訊.
*/
public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
// check for getStackTrace permission
SecurityManager 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 threads
Thread[] threads = getThreads();
StackTraceElement[][] traces = dumpThreads(threads);
Map<Thread, StackTraceElement[]> m = new HashMap<>(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;
}
/* 運作時許可常量*/
private static final RuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION =
new RuntimePermission("enableContextClassLoaderOverride");
/** cache of subclass security audit results */
/* Replace with ConcurrentReferenceHashMap when/if it appears in a future
* release */
private static class Caches {
/** cache of subclass security audit results */
static final ConcurrentMap<WeakClassKey, Boolean> subclassAudits = new ConcurrentHashMap<>();
/** queue for WeakReferences to audited subclasses */
static final ReferenceQueue<Class<?>> subclassAuditsQueue = new ReferenceQueue<>();
}
/**
* Verifies that this (possibly subclass) instance can be constructed without violating security constraints: the
* subclass must not override security-sensitive non-final methods, or else the "enableContextClassLoaderOverride"
* RuntimePermission is checked.
*/
private static boolean isCCLOverridden(Class<?> cl) {
if (cl == Thread.class)
return false;
processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
WeakClassKey key = new WeakClassKey(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();
}
/**
* Performs reflective checks on given subclass to verify that it doesn't override security-sensitive non-final
* methods. Returns true if the subclass overrides any of the methods, false otherwise.
*/
private static boolean auditSubclass(final Class<?> subcl) {
Boolean result = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
public Boolean run() {
for (Class<?> cl = subcl; cl != Thread.class; cl = cl.getSuperclass()) {
try {
cl.getDeclaredMethod("getContextClassLoader", new Class<?>[0]);
return Boolean.TRUE;
} catch (NoSuchMethodException ex) {
}
try {
Class<?>[] params = {ClassLoader.class};
cl.getDeclaredMethod("setContextClassLoader", params);
return Boolean.TRUE;
} catch (NoSuchMethodException ex) {
}
}
return Boolean.FALSE;
}
});
return result.booleanValue();
}
private native static StackTraceElement[][] dumpThreads(Thread[] threads);
private native static Thread[] getThreads();
/**
* 擷取目前線程,線程id
*/
public long getId() {
return tid;
}
/* 線程狀态枚舉 */
public enum State {
// 建立窗台,建立後還沒有執行start方法的線程
NEW,
// 運作中狀态,包含在運作中的線程以及在等待CPU排程的線程
RUNNABLE,
// 阻塞狀态,表示線程阻塞于鎖
BLOCKED,
// 等待狀态,一個線程處于wating狀态,是因為調用了下面方法中的某一個: 1.Object.wait 2.Thread.join 3.LockSupport.park
WAITING,
/**
*等待逾時狀态 線程等待指定時間. 這種狀态的出現是因為調用了下面方法中的某一個:
1.Thread.sleep() 2.Object.wait() 3.Thread.join() 4.LockSupport.parkNanos(), 5.LockSupport.parkUntil()
*/
TIMED_WAITING,
// 終止狀态,表示目前線程已經執行完畢。
TERMINATED;
}
/*傳回線程狀态. 這一方法的設計目的:用于系統狀态的監聽,而非同步控制. */
public State getState() {
// get current thread state
return sun.misc.VM.toThreadState(threadStatus);
}
// Added in JSR-166
/**
* 由于未捕獲異常而導緻線程終止的函數接口處理器. 當一個線程由于未捕獲異常而終止時,JVM将會使用getUncaughtExceptionHandler來查詢此線程的UncaughtExceptionHandler,
* 且會調用處理器handler的uncaughtException()方法,将此線程和其異常作為參數.
* 如果一個線程沒有它特定的UncaughtExceptionHandler,則它所屬的線程組對象充當其UncaughtExceptionHandler.
* 如果線程組對象沒有處理異常的指定請求,它可以向前調用getDefaultUncaughtExceptionHandler的預設處理異常的方法.
*/
@FunctionalInterface
public interface UncaughtExceptionHandler {
/**
* 由于未捕獲異常而導緻線程終止的方法調用. 此方法抛出的任何異常都會被JVM忽略.
*/
void uncaughtException(Thread t, Throwable e);
}
// null unless explicitly set
private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
// null unless explicitly set
private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
/**
* 設定預設處理器用于處理:由于未捕獲異常而導緻的線程終止,且此線程還未定義任何其它的處理器.
* 未捕獲異常首先由本線程進行處理,然後由線程所屬的線程組對象處理,最後由預設未捕獲異常處理器進行處理.
* 如果線程未設定明确的未捕獲異常處理器,且線程的線程組(包括父線程組)也未指定,則此時預設處理器的uncaughtException
* 方法會被執行.由于設定了預設的未捕獲異常處理器,則應用能夠更改未捕獲異常的處理方法.
* 注意:預設的未捕獲異常處理器不應該經常使用線程的線程組對象,因為這會引起無限遞歸.
*/
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("setDefaultUncaughtExceptionHandler"));
}
defaultUncaughtExceptionHandler = eh;
}
//當一個線程因未捕獲異常而突然終止時,傳回的預設處理器.
public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {
return defaultUncaughtExceptionHandler;
}
//傳回由于未捕獲異常而導緻線程中斷的處理器.如果此線程無未捕獲異常處理器,則傳回此線程的線程組對象
//如果此線程已經終止,則傳回null.
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
return uncaughtExceptionHandler != null ? uncaughtExceptionHandler : group;
}
/**
* 設定一個由于未捕獲異常而導緻線程中斷的處理器.
* 通過設定未捕獲異常處理器,一個線程可以完全控制如何處理未捕獲異常.
* 如果沒有設定未捕獲異常,則線程組對象預設為其未捕獲異常處理器.
*/
public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
checkAccess();
uncaughtExceptionHandler = eh;
}
//将未捕獲異常分發給處理器.這一方法通常被JVM調用.
private void dispatchUncaughtException(Throwable e) {
getUncaughtExceptionHandler().uncaughtException(this, e);
}
//删除指定map中那些在特定引用隊列中已經排隊的所有key
static void processQueue(ReferenceQueue<Class<?>> queue, ConcurrentMap<? extends WeakReference<Class<?>>, ?> map) {
Reference<? extends Class<?>> ref;
while ((ref = queue.poll()) != null) {
map.remove(ref);
}
}
/**
* Weak key for Class objects.
* WeakReference類說明:弱引用對象(JVM四種引用中的弱引用),這并不妨礙它們的引用對象被最終化、定型,然後回收.弱引用最常用于實作規範化映射。
**/
static class WeakClassKey extends WeakReference<Class<?>> {
/**
* saved value of the referent's identity hash code, to maintain a consistent hash code after the referent has
* been cleared
*/
private final int 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.
*/
@Override
public int hashCode() {
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.
*/
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (obj instanceof WeakClassKey) {
Object referent = get();
return (referent != null) && (referent == ((WeakClassKey)obj).get());
} else {
return false;
}
}
}
// 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 */
private native void setPriority0(int newPriority);
private native void stop0(Object o);
private native void suspend0();
private native void resume0();
private native void interrupt0();
private native void setNativeName(String name);
}
總結
- Thread.State
- 六種狀态:NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED
- start、start0
- 使該線程開始執行;Java 虛拟機調用該線程的 run 方法。
- 結果是兩個線程并發地運作;目前線程(從調用傳回給 start 方法)和另一個線程(執行其 run 方法)。
- 多次啟動一個線程是非法的。特别是當線程已經結束執行後,不能再重新啟動。
- run
- 如果該線程是使用獨立的 Runnable 運作對象構造的,則調用該 Runnable 對象的 run 方法;否則,該方法不執行任何操作并傳回。
- join
- 等待該線程終止的時間最長為 millis 毫秒。逾時為 0 意味着要一直等下去。
- sleep
- 在指定的毫秒數内讓目前正在執行的線程休眠(暫停執行),此操作受到系統計時器和排程程式精度和準确性的影響。該線程不丢失任何螢幕的所屬權。
- yield
- 暫停目前正在執行的線程對象,并執行其他線程。