前言
本文主要講述線程實現、線程狀態、線程優先級、守護線程、線程常用API以及線程中斷和停止。
一、線程實現
1、繼承Thread類,繼承後重寫run方法,調用start()方法就可以跑起來了
2、實現Runnable接口,實現後一定要重寫run方法,然後傳參給Thread類的構造函數創建出Thread對象,然後調用start(0方法
3、實現Callable接口,與Runnable相比,執行完run方法後有返回值,其它一致
二、線程狀態
線程共有5種狀態:
1、創建狀態:我們創建出一個線程對象後,它就進入了創建狀態
2、運行狀態:我們調用了start()方法後,線程進入了運行狀態,此時它可能正在運行,也可能正等待CPU分配時間片
3、等待狀態:此時線程在等待其他線程的喚醒或是等待一定時間後由系統喚醒,這又可以分爲:
無限等待狀態:線程不會被CPU分配時間片直到其他線程的喚醒,常見用例:
未設置Timeout參數的Object.wait()
未設置Timeout參數的Thread.join()
限期等待狀態:線程會在一定時間後被系統自動喚醒,常見用例:
設置了Timeout參數的Object.wait()
設置了Timeout參數的Thread.join()
Thread.sleep()方法
4、阻塞狀態:此時線程正在等待獲取一個排他鎖。
5、結束狀態:線程執行完run方法後進入結束狀態
三、線程優先級
Java線程的優先級共有10種,默認優先級爲5,最大爲10,最小爲1。線程的優先級並不意味着一定能先得到CPU的時間片分配,只是讓其更容易被系統選擇分配。值得我們注意的是,java線程是通過映射到系統的原生線程上實現的,所以線程調度最終還是取決於操作系統,比如windows線程優先級只有7種,因此java的幾個不同優先級映射到windows中就會出現相同的情況。
四、守護線程
守護線程也被稱爲後臺線程,如要設置必須在創建狀態也就是start前設置,守護線程是可以繼承的,如果當前所有的用戶線程都退出了,那麼守護線程也會退出。守護線程的常見實例就是JVM的GC線程。
五、線程中斷
我們調用interupt()方法使得線程進入中斷狀態,這時線程內部的中斷信號會被設置爲true。我們要在線程的執行體中通過線程的中斷檢查事件(isInterrupted())判斷有無進入中斷狀態,一般而言我們會用while(Thread.currentThread().isInterrupted()){}的語法。
六、線程常用API
1、設置線程本身屬性
編號 | 方法 | 說明 |
1 | public final void setName(String name) | 設置線程名稱 |
2 | public final void setPriority(int priority) | 設置線程優先級,默認爲5 |
3 | public final void setDaemon(boolean on) | 將線程標記爲守護線程或是用戶線程 |
2、 其他常用方法
編號 | 方法 | 說明 |
1 | public void start() | 調用它使線程進入運行狀態 |
2 | public void run() | 線程運行的任務 |
3 | public final void join();public final void join(long millisec) | 主線程等待該線程運行完畢 |
4 | public void interrupt() | 設置線程中斷信號爲true |
5 | public final native boolean isAlive() | 判斷線程是否處於運行狀態 |
6 | public static Thread currentThread() | 返回當前的對象實例 |
7 | public static native void sleep(long millisec) | 當前線程交出CPU時間片但不釋放對象鎖,一般用於線程暫停 |
8 | public static native void yield() | 暫停當前執行的線程,線程進入限期等待狀態 |
七、 常見問題
1、start()方法與run()方法有什麼不同?
start()方法用於啓動線程,使線程進入運行狀態,而run()方法只是實現了線程任務的一個方法,單獨運行run()方法只是讓主線程去執行了一個普通方法,並沒有創建新線程。
2、sleep()方法和wait()方法有什麼不同?
①、sleep()方法只是阻塞了線程,並未釋放鎖,wait()方法釋放了鎖;②、sleep()是Thread類下的方法,wait()方法是Object類的;3、sleep()方法一般用於暫停線程,wait()通常用於線程間的交互和通信
3、yield()和sleep()有什麼不同?
①、yield()方法執行後線程只是釋放了當前的時間片,隨時可以獲取時間片重新運行,sleep則是進入等待狀態,需要一定時間後才能重獲時間片運行;2、yield()方法只會將CPU時間片獲取機會給優先級相同或更高的線程,而sleep()方法則是一視同仁,任何線程都有機會獲取時間片;3、sleep()必須聲明InterruptedException而yield不必。
4、繼承Thread類和實現Runnable接口有什麼不同?
①我們都知道java只能單繼承,而可以實現多個接口,實現Runnable後可以繼承其他的類;②、實現Runnable接口,接口中的方法可以被其他線程共享。