1.線程的概念

提到線程,我們就不得不提到另外一個與之相似的概念:進程。何為進程?進程就是一個程序一次動態的執行過程,即計算機中一個任務的執行。在使用計算機的過程中,例如:打開酷狗軟件聽音樂,登錄QQ與好友互動,Java虛擬機的啟動等等,都對應著計算機中的一個個進程,進程是操作系統進行資源分配的基本單位
那么什么又是線程呢?如果進程是一個大的任務,那么線程就是這個大任務中一個個具體的子任務,我們可以把線程看成是一個更加輕量級的進程。在使用酷狗軟件時,我們既可以一邊播放音樂,一邊下載歌曲,同時還可以設置背景顏色,這些一個個的具體操作就是線程,線程是CPU調度的基本單位

2.線程的創建

創建線程有兩種常見的方式:繼承java.lang.Thread類和實現Runnable接口
繼承Thread類,重寫run方法,在run方法中定義需要執行的任務

public class MyThread extends Thread {
    @Override
    public void run(){}  
}
Thread thread = new MyThread();
thread.start(); 

實現Runnable接口,重寫run方法,在run方法中定義需要執行的任務

Runnable r = () -> {
  // 具體實現
};
Thread thread = new Thread(r);
thread.start();

創建線程的兩種方式的比較
相比于第一種繼承Thread類創建線程的方式,更加推薦使用第二種方式,因為第二種方式實現了線程的創建與具體執行的任務之間的解耦,并且在實現Runnable接口時同時可以繼承其它的類

3.線程的狀態

線程有6種狀態:
NEW(新建)
RUNNABLE(可運行)
BLOCKED(阻塞)
WAITING(等待)
TIMED_WAITING(計時等待)
TERMINATED(被終止)
線程各個狀態的轉換:
線程狀態轉換.png

4.線程常用方法

void start()
調用start()方法將會啟動一個新的線程,當該線程獲得CPU執行權后,將引發調用run()方法,執行用戶定義的子任務

void run()
當啟動一個新的線程并獲得CPU執行權后,便自動調用run()方法去執行具體的子任務。 注意,如果直接調用run()方法,那么系統將不會啟動一個新的線程,而是將run()方法作為一個普通方法運行

static native void sleep(long millis)
sleep()方法讓線程休眠給定的時間,同時放棄CPU的執行權,此時線程進入TIMED_WAITING狀態
注意,如果當前線程持有某個對象的鎖,調用sleep()方法不會釋放該鎖

static native void yield()
調用yield方法會讓當前線程放棄CPU的執行權,它跟sleep方法類似,同樣不會釋放鎖,但是yield不能控制具體的交出CPU的時間
另外,yield方法只能讓擁有相同優先級的線程有獲取CPU執行權的機會
注意,調用yield方法并不會讓線程進入阻塞狀態,而是讓線程重回可運行狀態

final void join()
調用thread.join()方法,當前線程將等待thread執行完畢,如果調用的是指定了時間參數的join方法,則等待指定的時間

void interrupt()
向線程發送中斷請求,線程的中斷狀態將被置為true。如果目前該線程被一個sleep調用阻塞,那么InterruptedException異常被拋出

boolean isInterrupted()
測試線程是否被終止,不改變中斷狀態

static boolean interrupted()
測試當前線程(正在執行這一命令的線程)是否被中斷
注意:調用該方法將會使當前線程的中斷狀態重置為false