Thread源码阅读
Thread實現(xiàn)Runnable接口
1.Thread內(nèi)部有個State枚舉,標示著線程的狀態(tài)。
- NEW,新建未開始
- RUNNABLE,可執(zhí)行
- BLOCKED,阻塞狀態(tài),等待一個monitor lock,或者Object.wait()之后重入一個synchronized鎖定的代碼
- WAITING,等待狀態(tài),Object.wait(),Thread.join(),LockSupport.park()之后進入此狀態(tài)
- TIMED_WAITING,帶超時時間的等待狀態(tài),Object.wait(long),Thread.join(long),LockSupport.parkNanos(),LockSupport.parkUntil()之后進入此狀態(tài)
- TERMINATED,終止狀態(tài)
2.接著看下Thread的構造函數(shù)及其幾個相關的成員變量
/* 帶目標run對象. */private Runnable target;/* 線程組 */private ThreadGroup group;/* 此線程的類加載器 */private ClassLoader contextClassLoader;/* 想要的棧大小,為0時此參數(shù)被忽略,且有VM不支持此參數(shù) */private long stackSize;/* 狀態(tài)標識,0代表新建未開始*/private volatile int threadStatus = 0;/* 靜態(tài)native方法,返回當前線程*/public static native Thread currentThread();public Thread() {init(null, null, "Thread-" + nextThreadNum(), 0);}public Thread(Runnable target) {init(null, target, "Thread-" + nextThreadNum(), 0);}Thread(Runnable target, AccessControlContext acc) {init(null, target, "Thread-" + nextThreadNum(), 0, acc);}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);}/*** Initializes a Thread.** @param g 線程組* @param target 要執(zhí)行的帶run的目標對象* @param name 線程名* @param stackSize 新線程的棧大小,等于0時可忽略此參數(shù)* @param acc 接入控制上下文*/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;Thread parent = currentThread();SecurityManager security = System.getSecurityManager();//獲取線程組if (g == null) {/* 從SecurityManager拿線程組 */if (security != null) {g = security.getThreadGroup();}/* 如果還沒拿到從當前線程拿*/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();elsethis.contextClassLoader = parent.contextClassLoader;this.inheritedAccessControlContext =acc != null ? acc : AccessController.getContext();this.target = target;setPriority(priority);//從父線程繼承可繼承的ThreadLocalif (parent.inheritableThreadLocals != null)this.inheritableThreadLocals =ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);this.stackSize = stackSize;/* 設置線程ID */tid = nextThreadID();}不同的構造函數(shù)很多,最終都調init方法,init主要實現(xiàn)的就是把相應的參數(shù)放入成員變量里,ThreadGroup的獲取,接入控制,inheritableThreadLocals父繼承,線程id自增。
3.調用線程執(zhí)行的主方法start及run方法
/* 線程啟動方法 */public synchronized void start() {/*** 如果線程不是NEW狀態(tài),則拋異常*/if (threadStatus != 0)throw new IllegalThreadStateException();/*通知線程組此線程準備運行里,所以它可以加入到線程組列表中,線程組的未開始數(shù)量可以減少了 */group.add(this);boolean started = false;try {start0();started = true;} finally {try {if (!started) {group.threadStartFailed(this);}} catch (Throwable ignore) {/*什么都不做,如果start0排除一個異常,它已經(jīng)可以被調用棧知道 */}}}private native void start0();start方法主要也是native實現(xiàn),真正開始之前校驗了狀態(tài),并接入ThreadGroup管理。
/* Runnale 接口的方法*/@Overridepublic void run() {if (target != null) {target.run();}}真正的run其實是目標類的run方法
4.join方法,等待線程掛掉的方法,會拋出InterruptedException
/*如果這個線程還活著就一直等待*/public final void join() throws InterruptedException {join(0);} /*如果這個線程還活著就一直等待millis時間*/ 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;}}}Thread里為數(shù)不多的純Java代碼,它被synchronized標記,實現(xiàn)主要是自旋方法檢驗線程是否活著,如果活著,則wait釋放鎖,還有疑問請移步join的討論
6.sleep方法,native實現(xiàn),會拋出InterruptedException
/* 睡眠指定毫秒,并不釋放monitor*/public static native void sleep(long millis) throws InterruptedException;7.yield方法,native實現(xiàn)
/*使當前線程從執(zhí)行狀態(tài)(運行狀態(tài))變?yōu)榭蓤?zhí)行態(tài)(就緒狀態(tài))。cpu會從眾多的可執(zhí)行態(tài)里選擇,也就是說,當前也就是剛剛的那個線程還是有可能會被再次執(zhí)行到的,并不是說一定會執(zhí)行其他線程而該線程在下一次中不會執(zhí)行到了*/public static native void yield();7.interrupt方法,更多關于中斷的請見處理中斷
每個線程都有一個與之相關聯(lián)的 Boolean 屬性,用于表示線程的中斷狀態(tài)(interrupted status)。中斷狀態(tài)初始時為 false;當另一個線程通過調用 Thread.interrupt() 中斷一個線程時,會出現(xiàn)以下兩種情況之一。如果那個線程在執(zhí)行一個低級可中斷阻塞方法,例如 Thread.sleep()、 Thread.join() 或 Object.wait(),那么它將取消阻塞并拋出 InterruptedException。否則, interrupt() 只是設置線程的中斷狀態(tài)。 在被中斷線程中運行的代碼以后可以輪詢中斷狀態(tài),看看它是否被請求停止正在做的事情。中斷狀態(tài)可以通過 Thread.isInterrupted() 來讀取,并且可以通過一個名為 Thread.interrupted() 的操作讀取和清除。
中斷是一種協(xié)作機制。當一個線程中斷另一個線程時,被中斷的線程不一定要立即停止正在做的事情。相反,中斷是禮貌地請求另一個線程在它愿意并且方便的時候停止它正在做的事情。有些方法,例如 Thread.sleep(),很認真地對待這樣的請求,但每個方法不是一定要對中斷作出響應。對于中斷請求,不阻塞但是仍然要花較長時間執(zhí)行的方法可以輪詢中斷狀態(tài),并在被中斷的時候提前返回。 您可以隨意忽略中斷請求,但是這樣做的話會影響響應。
中斷的協(xié)作特性所帶來的一個好處是,它為安全地構造可取消活動提供更大的靈活性。我們很少希望一個活動立即停止;如果活動在正在進行更新的時候被取消,那么程序數(shù)據(jù)結構可能處于不一致狀態(tài)。中斷允許一個可取消活動來清理正在進行的工作,恢復不變量,通知其他活動它要被取消,然后才終止。
其它還有很多調試的方法activeCount,dumpStack就不討論了
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結
以上是生活随笔為你收集整理的Thread源码阅读的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android中的一个定时任务的方法
- 下一篇: tabBar颜色改动