Java虛擬機棧
JVM中由堆、棧、方法區所組成,其中棧內存是給線程使用,每一個線程啓動後,虛擬機就會爲其分配一塊棧內存。java
由於如下一些緣由致使cpu再也不執行當前的線程,轉而執行另外一個線程的代碼編程
方法名 | 功能說明 | 注意 |
---|---|---|
start() | 啓動一個新線程,在新的線程運行run方法中的代碼 | start方法只是讓線程進入就緒,裏面的代碼不必定馬上運行(CPU的時間片還沒分給它)。每一個線程對象的start方法只能調用一次,若是調用了屢次會出現IllegalThreadStateException |
run() | 新線程啓動後會調用的方法 | 若是在構造Thread對象時傳遞了Runnable參數,則線程啓動後調用Runnable中的run 方法,不然默認不執行任何操做。但能夠建立Thread的子類對象,來覆蓋默認行爲 |
join() | 等待線程運行結束 | |
join(long n) | 等待線程運行結束,最多等待n毫秒 | |
getId() | 獲取線程長整型的id | id惟一 |
getName() | 獲取線程名 | |
setName(String) | 修改線程名 | |
getPriority() | 獲取線程優先級 | |
setPriority(int) | 修改線程優先級 | java中規定線程優先級是1~10的整數,較大的優先級能提升該線程被CPU調度的機率 |
getState() | 獲取線程狀態 | java中線程狀態是用6個enum表示,分別爲 :NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED |
isInterrupted() | 斷定是否被打斷 | 不會清除打斷標記 |
isAlive() | 線程是否存活(尚未運行完畢) | |
interrupt() | 打斷線程 | 若是被打斷線程正在sleep,wait,join會致使被打斷的線程拋出InterruptedException,並清除打斷標記;若是打斷的正在運行的線程,則會設置打斷標記;park的線程被打斷,也會設置打斷標記 |
interrupted() static | 斷定當前線程是否被打斷 | 會清除打斷標記 |
currendThread(0 static | 獲取當前正在執行的線程 | |
sleep(long n) static | 讓當前執行的線程休眠n毫秒,休眠時讓出cpu的時間片給其餘線程 | |
yieId() static | 提示線程調度器讓出當前線程對CPU的使用 | 主要是爲了測試和調試 |
調用run
輸出
程序仍在main線程運行,FileReader.read()方法調用仍是同步的併發
sleepapp
sleep實現
在沒有利用cpu來計算時,不要讓while(true)空轉浪費cpu,這時可使用yield或sleep來讓出cpu的使用權給其餘程序異步
爲何須要join
下面的代碼執行,打印r是什麼?
分析jvm
打斷sleep,wait,join的線程
打斷sleep的線程,會清空打斷狀態,以sleep爲例
輸出
打斷正常運行的線程
打斷正常運行的線程,不會清空打斷狀態
輸出測試
Two Phase Termination
在一個線程T1中如何「優雅」終止線程T2?這裏的【優雅】指的是給T2一個料理後事的機會。
一、 錯誤思路操作系統
package com.example.demo; import lombok.extern.slf4j.Slf4j; @Slf4j public class TwoPhaseTermination { public static void main(String[] args) throws InterruptedException { Test test = new Test(); test.start(); Thread.sleep(3500); test.stop(); } } @Slf4j class Test{ private Thread monitor; /** * 啓動監控線程 */ public void start() { monitor = new Thread(() -> { while (true) { Thread currentThread = Thread.currentThread(); if (currentThread.isInterrupted()) { log.info("料理後事"); break; } try { // 狀況1 Thread.sleep(1000); log.info("執行監控記錄"); } catch (Exception e) { // 由於sleep出現異常後,會消除打斷標記 // 須要重置打斷標記 e.printStackTrace(); currentThread.interrupt(); } } }); monitor.start(); } /** * 中止監控線程 */ public void stop() { monitor.interrupt(); } }
打斷park線程
打斷park線程,不會清空打斷狀態
輸出
若是打斷標記已是true,則park會失效,能夠以下操做 :.net
還有一些不推薦使用的方法,這些方法已過期,容易破壞同步代碼塊,形成線程死鎖。線程
方法名 | static | 功能說明 |
---|---|---|
stop() | 中止線程運行 | |
suspend() | 掛起(暫停)線程運行 | |
resume() | 恢復線程運行 |
默認狀況下,Java進程須要等待全部線程都運行結束,纔會結束。有一種特殊的線程叫作守護線程,只要其它非守護線程運行結束了,即便守護線程的代碼沒有執行完,也會強制結束。
注意