Java并發(fā)編程之線程基礎(chǔ)
1.線程的概念
提到線程,我們就不得不提到另外一個(gè)與之相似的概念:進(jìn)程。何為進(jìn)程?進(jìn)程就是一個(gè)程序一次動(dòng)態(tài)的執(zhí)行過程,即計(jì)算機(jī)中一個(gè)任務(wù)的執(zhí)行。在使用計(jì)算機(jī)的過程中,例如:打開酷狗軟件聽音樂,登錄QQ與好友互動(dòng),Java虛擬機(jī)的啟動(dòng)等等,都對(duì)應(yīng)著計(jì)算機(jī)中的一個(gè)個(gè)進(jìn)程,進(jìn)程是操作系統(tǒng)進(jìn)行資源分配的基本單位
那么什么又是線程呢?如果進(jìn)程是一個(gè)大的任務(wù),那么線程就是這個(gè)大任務(wù)中一個(gè)個(gè)具體的子任務(wù),我們可以把線程看成是一個(gè)更加輕量級(jí)的進(jìn)程。在使用酷狗軟件時(shí),我們既可以一邊播放音樂,一邊下載歌曲,同時(shí)還可以設(shè)置背景顏色,這些一個(gè)個(gè)的具體操作就是線程,線程是CPU調(diào)度的基本單位
2.線程的創(chuàng)建
創(chuàng)建線程有兩種常見的方式:繼承java.lang.Thread類和實(shí)現(xiàn)Runnable接口
繼承Thread類,重寫run方法,在run方法中定義需要執(zhí)行的任務(wù)
public class MyThread extends Thread {
@Override
public void run(){}
}
Thread thread = new MyThread();
thread.start();
實(shí)現(xiàn)Runnable接口,重寫run方法,在run方法中定義需要執(zhí)行的任務(wù)
Runnable r = () -> {
// 具體實(shí)現(xiàn)
};
Thread thread = new Thread(r);
thread.start();
創(chuàng)建線程的兩種方式的比較
相比于第一種繼承Thread類創(chuàng)建線程的方式,更加推薦使用第二種方式,因?yàn)榈诙N方式實(shí)現(xiàn)了線程的創(chuàng)建與具體執(zhí)行的任務(wù)之間的解耦,并且在實(shí)現(xiàn)Runnable接口時(shí)同時(shí)可以繼承其它的類
3.線程的狀態(tài)
線程有6種狀態(tài):
NEW(新建)
RUNNABLE(可運(yùn)行)
BLOCKED(阻塞)
WAITING(等待)
TIMED_WAITING(計(jì)時(shí)等待)
TERMINATED(被終止)
線程各個(gè)狀態(tài)的轉(zhuǎn)換:

4.線程常用方法
void start()
調(diào)用start()方法將會(huì)啟動(dòng)一個(gè)新的線程,當(dāng)該線程獲得CPU執(zhí)行權(quán)后,將引發(fā)調(diào)用run()方法,執(zhí)行用戶定義的子任務(wù)
void run()
當(dāng)啟動(dòng)一個(gè)新的線程并獲得CPU執(zhí)行權(quán)后,便自動(dòng)調(diào)用run()方法去執(zhí)行具體的子任務(wù)。 注意,如果直接調(diào)用run()方法,那么系統(tǒng)將不會(huì)啟動(dòng)一個(gè)新的線程,而是將run()方法作為一個(gè)普通方法運(yùn)行
static native void sleep(long millis)
sleep()方法讓線程休眠給定的時(shí)間,同時(shí)放棄CPU的執(zhí)行權(quán),此時(shí)線程進(jìn)入TIMED_WAITING狀態(tài)
注意,如果當(dāng)前線程持有某個(gè)對(duì)象的鎖,調(diào)用sleep()方法不會(huì)釋放該鎖
static native void yield()
調(diào)用yield方法會(huì)讓當(dāng)前線程放棄CPU的執(zhí)行權(quán),它跟sleep方法類似,同樣不會(huì)釋放鎖,但是yield不能控制具體的交出CPU的時(shí)間
另外,yield方法只能讓擁有相同優(yōu)先級(jí)的線程有獲取CPU執(zhí)行權(quán)的機(jī)會(huì)
注意,調(diào)用yield方法并不會(huì)讓線程進(jìn)入阻塞狀態(tài),而是讓線程重回可運(yùn)行狀態(tài)
final void join()
調(diào)用thread.join()方法,當(dāng)前線程將等待thread執(zhí)行完畢,如果調(diào)用的是指定了時(shí)間參數(shù)的join方法,則等待指定的時(shí)間
void interrupt()
向線程發(fā)送中斷請(qǐng)求,線程的中斷狀態(tài)將被置為true。如果目前該線程被一個(gè)sleep調(diào)用阻塞,那么InterruptedException異常被拋出
boolean isInterrupted()
測試線程是否被終止,不改變中斷狀態(tài)
static boolean interrupted()
測試當(dāng)前線程(正在執(zhí)行這一命令的線程)是否被中斷
注意:調(diào)用該方法將會(huì)使當(dāng)前線程的中斷狀態(tài)重置為false
