Thread類用於操作線程,是所以涉及到線程操作(如併發)的基礎。本文將通過源碼對Thread類的功能作用進行分析。
一、屬性
/* Make sure registerNatives is the first thing <clinit> does. */
private static native void registerNatives();
static {
registerNatives();
}
private volatile String 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;
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();
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;
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;
}
此處重點說一下線程的優先級和狀態。
1.線程優先級
private int priority;
public final static int MIN_PRIORITY = 1;
public final static int NORM_PRIORITY = 5;
public final static int MAX_PRIORITY = 10;
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;
}
線程執行有優先級,優先級越高先執行機會越大(並不是一定先執行!!)。優先級用int的priority參數表示。
線程優先級最高爲10,最低爲1。默認爲5
2.線程的狀態
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
public State getState() {
return sun.misc.VM.toThreadState(threadStatus);
}
Thread對象共有6種狀態:NEW(新建),RUNNABLE(運行),BLOCKED(阻塞),WAITING(等待),TIMED_WAITING(有時間的等待),TERMINATED(終止);狀態轉換如下:
也有一種說法,我認爲也可以:
線程只有”就緒”、”阻塞”、”運行”三種狀態(新建[NEW]”和”終止[TERMINATED]”狀態的線程並不是線程,只是代表一個線程對象還存在):
1. RUNNABLE,對應”就緒”和”運行”兩種狀態,也就是說處於就緒和運行狀態的線程在java.lang.Thread中都表現爲”RUNNABLE”
2. BLOCKED,對應”阻塞”狀態,此線程需要獲得某個鎖才能繼續執行,而這個鎖目前被其他線程持有,所以進入了被動的等待狀態,直到搶到了那個鎖,纔會再次進入”就緒”狀態
3. WAITING,對應”阻塞”狀態,代表此線程正處於無限期的主動等待中,直到有人喚醒它,它纔會再次進入就緒狀態
4. TIMED_WAITING,對應”阻塞”狀態,代表此線程正處於有限期的主動等待中,要麼有人喚醒它,要麼等待夠了一定時間之後,纔會再次進入就緒狀態
二、構造器
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
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);
}
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
public Thread(ThreadGroup group, Runnable target, String name) {
init(group, target, name, 0);
}
public Thread(ThreadGroup group, Runnable target, String name,
long stackSize) {
init(group, target, name, stackSize);
}
private void init(ThreadGroup g, Runnable target, String name,long stackSize) {
init(g, target, name, stackSize, null, true);
}
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
if (name == null) {
throw new NullPointerException("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();
}
}
g.checkAccess();
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
g.addUnstarted();
this.group = g;
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
this.target = target;
setPriority(priority);
if (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();
}
通過以上代碼可以看出,Thread()對外提供了8個構造器,但是都是接收不同參數,然後調用init(ThreadGroup g, Runnable target, String name, long stackSize)方法。故我們只需分析次init()方法即可。
init()方法共有4個參數,分別代表:
- ThreadGroup g 指定當前線程的線程組,未指定時線程組爲創建該線程所屬的線程組。線程組可以用來管理一組線程,通過activeCount() 來查看活動線程的數量。其他沒有什麼大的用處。
- Runnable target 指定運行其中的Runnable,一般都需要指定,不指定的線程沒有意義,或者可以通過創建Thread的子類並重新run方法。
- String name 線程的名稱,不指定自動生成。
- long stackSize 預期堆棧大小,不指定默認爲0,0代表忽略這個屬性。與平臺相關,不建議使用該屬性。
三、public方法
Thread Thread.currentThread() :獲得當前線程的引用。獲得當前線程後對其進行操作。與this是有區別的。
Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() :返回線程由於未捕獲到異常而突然終止時調用的默認處理程序。
int Thread.activeCount():當前線程所在線程組中活動線程的數目。
void dumpStack() :將當前線程的堆棧跟蹤打印至標準錯誤流。
int enumerate(Thread[] tarray) :將當前線程的線程組及其子組中的每一個活動線程複製到指定的數組中。
Map<Thread,StackTraceElement[]> getAllStackTraces() :返回所有活動線程的堆棧跟蹤的一個映射。
boolean holdsLock(Object obj) :當且僅當當前線程在指定的對象上保持監視器鎖時,才返回 true。
boolean interrupted() :測試當前線程是否已經中斷。
void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) :設置當線程由於未捕獲到異常而突然終止,並且沒有爲該線程定義其他處理程序時所調用的默認處理程序。
void sleep(long millis) :休眠指定時間
void sleep(long millis, int nanos) :休眠指定時間
void yield() :暫停當前正在執行的線程對象,並執行其他線程。意義不太大
void checkAccess() :判定當前運行的線程是否有權修改該線程。
ClassLoader getContextClassLoader() :返回該線程的上下文 ClassLoader。
long getId() :返回該線程的標識符。
String getName() :返回該線程的名稱。
int getPriority() :返回線程的優先級。
StackTraceElement[] getStackTrace() :返回一個表示該線程堆棧轉儲的堆棧跟蹤元素數組。
Thread.State getState() :返回該線程的狀態。
ThreadGroup getThreadGroup() :返回該線程所屬的線程組。
Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() :返回該線程由於未捕獲到異常而突然終止時調用的處理程序。
void interrupt() :中斷線程。
boolean isAlive() :測試線程是否處於活動狀態。
boolean isDaemon() :測試該線程是否爲守護線程。
boolean isInterrupted():測試線程是否已經中斷。
void join() :等待該線程終止。
void join(long millis) :等待該線程終止的時間最長爲 millis 毫秒。
void join(long millis, int nanos) :等待該線程終止的時間最長爲 millis 毫秒 + nanos 納秒。
void run() :線程啓動後執行的方法。
void setContextClassLoader(ClassLoader cl) :設置該線程的上下文 ClassLoader。
void setDaemon(boolean on) :將該線程標記爲守護線程或用戶線程。
void start():使該線程開始執行;Java 虛擬機調用該線程的 run 方法。
String toString():返回該線程的字符串表示形式,包括線程名稱、優先級和線程組。
---------------------
作者:MartinCol
來源:CSDN
原文:https://blog.csdn.net/pengqiaowolf/article/details/80442071
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!