本文目錄
- 線程與多線程
- 線程的運(yùn)行與創(chuàng)建
- 線程的狀態(tài)
1 線程與多線程
線程是什么?
線程(Thread)是一個(gè)對象(Object)冕茅。用來干什么?Java 線程(也稱 JVM 線程)是 Java 進(jìn)程內(nèi)允許多個(gè)同時(shí)進(jìn)行的任務(wù)汽烦。該進(jìn)程內(nèi)并發(fā)的任務(wù)成為線程(Thread)瑰煎,一個(gè)進(jìn)程里至少一個(gè)線程。
Java 程序采用多線程方式來支持大量的并發(fā)請求處理技肩,程序如果在多線程方式執(zhí)行下且轨,其復(fù)雜度遠(yuǎn)高于單線程串行執(zhí)行。那么多線程:指的是這個(gè)程序(一個(gè)進(jìn)程)運(yùn)行時(shí)產(chǎn)生了不止一個(gè)線程。
為啥使用多線程旋奢?
- 適合多核處理器泳挥。一個(gè)線程運(yùn)行在一個(gè)處理器核心上,那么多線程可以分配到多個(gè)處理器核心上至朗,更好地利用多核處理器屉符。
- 防止阻塞。將數(shù)據(jù)一致性不強(qiáng)的操作使用多線程技術(shù)(或者消息隊(duì)列)加快代碼邏輯處理锹引,縮短響應(yīng)時(shí)間矗钟。
聊到多線程,多半會(huì)聊并發(fā)與并行嫌变,咋理解并區(qū)分這兩個(gè)的區(qū)別呢吨艇?
- 類似單個(gè) CPU ,通過 CPU 調(diào)度算法等初澎,處理多個(gè)任務(wù)的能力秸应,叫并發(fā)
- 類似多個(gè) CPU ,同時(shí)并且處理相同多個(gè)任務(wù)的能力碑宴,叫做并行
2 線程的運(yùn)行與創(chuàng)建
2.1 線程的創(chuàng)建
Java 創(chuàng)建線程對象有兩種方法:
- 繼承 Thread 類創(chuàng)建線程對象
- 實(shí)現(xiàn) Runnable 接口類創(chuàng)建線程對象
新建 MyThread 對象软啼,代碼如下:
/**
* 繼承 Thread 類創(chuàng)建線程對象
* @author Jeff Lee @ bysocket.com
* @since 2018年01月27日21:03:02
*/
public class MyThread extends Thread {
@Override // 可以省略
public void run() {
System.out.println("MyThread 的線程對象正在執(zhí)行任務(wù)");
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
MyThread thread = new MyThread();
thread.start();
System.out.println("MyThread 的線程對象 " + thread.getId());
}
}
}
MyThread 類繼承了 Thread 對象,并重寫(Override)了 run 方法延柠,實(shí)現(xiàn)線程里面的邏輯祸挪。main 函數(shù)是使用 for 語句,循環(huán)創(chuàng)建了 10 個(gè)線程贞间,調(diào)用 start 方法啟動(dòng)線程贿条,最后打印當(dāng)前線程對象的 ID。
run 方法和 start 方法的區(qū)別是什么呢增热?
run 方法就是跑的意思整以,線程啟動(dòng)后,會(huì)調(diào)用 run 方法峻仇。
start 方法就是啟動(dòng)的意思公黑,就是啟動(dòng)新線程實(shí)例。啟動(dòng)線程后摄咆,才會(huì)調(diào)線程的 run 方法凡蚜。
執(zhí)行 main 方法后,控制臺(tái)打印如下:
MyThread 的線程對象正在執(zhí)行任務(wù)
MyThread 的線程對象 10
MyThread 的線程對象正在執(zhí)行任務(wù)
MyThread 的線程對象 11
MyThread 的線程對象正在執(zhí)行任務(wù)
MyThread 的線程對象 12
MyThread 的線程對象正在執(zhí)行任務(wù)
MyThread 的線程對象 13
MyThread 的線程對象正在執(zhí)行任務(wù)
MyThread 的線程對象 14
MyThread 的線程對象正在執(zhí)行任務(wù)
MyThread 的線程對象 15
MyThread 的線程對象正在執(zhí)行任務(wù)
MyThread 的線程對象 16
MyThread 的線程對象正在執(zhí)行任務(wù)
MyThread 的線程對象 17
MyThread 的線程對象正在執(zhí)行任務(wù)
MyThread 的線程對象 18
MyThread 的線程對象正在執(zhí)行任務(wù)
MyThread 的線程對象 19
可見吭从,線程的 ID 是線程唯一標(biāo)識(shí)符朝蜘,每個(gè)線程 ID 都是不一樣的。
start 方法和 run 方法的關(guān)系如圖所示:
同理涩金,實(shí)現(xiàn) Runnable 接口類創(chuàng)建線程對象也很簡單谱醇,只是不同的形式暇仲。新建 MyThreadBrother 代碼如下:
/**
* 實(shí)現(xiàn) Runnable 接口類創(chuàng)建線程對象
* @author Jeff Lee @ bysocket.com
* @since 2018年01月27日21:22:57
*/
public class MyThreadBrother implements Runnable {
@Override // 可以省略
public void run() {
System.out.println("MyThreadBrother 的線程對象正在執(zhí)行任務(wù)");
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(new MyThreadBrother());
thread.start();
System.out.println("MyThreadBrother 的線程對象 " + thread.getId());
}
}
}
具體代碼:「java-concurrency-core-learning」
https://github.com/JeffLi1993/java-concurrency-core-learning
2.1 線程的運(yùn)行
在運(yùn)行上面兩個(gè)小 demo 后,JVM 執(zhí)行了 main 函數(shù)線程枣抱,然后在主線程中執(zhí)行創(chuàng)建了新的線程熔吗。正常情況下,所有線程執(zhí)行到運(yùn)行結(jié)束為止佳晶。除非某個(gè)線程中調(diào)用了 System.exit(1) 則被終止桅狠。
在實(shí)際開發(fā)中,一個(gè)請求到響應(yīng)式是一個(gè)線程轿秧。但在這個(gè)線程中可以使用線程池創(chuàng)建新的線程中跌,去執(zhí)行任務(wù)。
3 線程的狀態(tài)
新建 MyThreadInfo 類菇篡,打印線程對象屬性漩符,代碼如下:
/**
* 線程實(shí)例對象的屬性值
* @author Jeff Lee @ bysocket.com
* @since 2018年01月27日21:24:40
*/
public class MyThreadInfo extends Thread {
@Override // 可以省略
public void run() {
System.out.println("MyThreadInfo 的線程實(shí)例正在執(zhí)行任務(wù)");
// System.exit(1);
}
public static void main(String[] args) {
MyThreadInfo thread = new MyThreadInfo();
thread.start();
System.out.print("MyThreadInfo 的線程對象 \n"
+ "線程唯一標(biāo)識(shí)符:" + thread.getId() + "\n"
+ "線程名稱:" + thread.getName() + "\n"
+ "線程狀態(tài):" + thread.getState() + "\n"
+ "線程優(yōu)先級(jí):" + thread.getPriority());
}
}
執(zhí)行代碼打印如下:
MyThreadInfo 的線程實(shí)例正在執(zhí)行任務(wù)
MyThreadInfo 的線程對象
線程唯一標(biāo)識(shí)符:10
線程名稱:Thread-0
線程狀態(tài):NEW
線程優(yōu)先級(jí):5
線程是一個(gè)對象,它有唯一標(biāo)識(shí)符 ID驱还、名稱嗜暴、狀態(tài)、優(yōu)先級(jí)等屬性议蟆。線程只能修改其優(yōu)先級(jí)和名稱等屬性 闷沥,無法修改 ID 、狀態(tài)咐容。ID 是 JVM 分配的舆逃,名字默認(rèn)也為 Thread-XX,XX是一組數(shù)字戳粒。線程初始狀態(tài)為 NEW路狮。
線程優(yōu)先級(jí)的范圍是 1 到 10 ,其中 1 是最低優(yōu)先級(jí)蔚约,10 是最高優(yōu)先級(jí)奄妨。不推薦改變線程的優(yōu)先級(jí),如果業(yè)務(wù)需要苹祟,自然可以修改線程優(yōu)先級(jí)到最高砸抛,或者最低。
線程的狀態(tài)實(shí)現(xiàn)通過 Thread.State 常量類實(shí)現(xiàn)苔咪,有 6 種線程狀態(tài):new(新建)锰悼、runnnable(可運(yùn)行)柳骄、blocked(阻塞)团赏、waiting(等待)、time waiting (定時(shí)等待)和 terminated(終止)耐薯。狀態(tài)轉(zhuǎn)換圖如下:
線程狀態(tài)流程大致如下:
- 線程創(chuàng)建后舔清,進(jìn)入 new 狀態(tài)
- 調(diào)用 start 或者 run 方法丝里,進(jìn)入 runnable 狀態(tài)
- JVM 按照線程優(yōu)先級(jí)及時(shí)間分片等執(zhí)行 runnable 狀態(tài)的線程。開始執(zhí)行時(shí)体谒,進(jìn)入 running 狀態(tài)
- 如果線程執(zhí)行 sleep杯聚、wait、join抒痒,或者進(jìn)入 IO 阻塞等幌绍。進(jìn)入 wait 或者 blocked 狀態(tài)
- 線程執(zhí)行完畢后,線程被線程隊(duì)列移除故响。最后為 terminated 狀態(tài)傀广。
4 小結(jié)
本文介紹了線程與多線程的基礎(chǔ)篇,包括了線程啟動(dòng)及線程狀態(tài)等彩届。下一篇我們聊下線程的具體操作伪冰。包括中斷、終止等
具體代碼:「java-concurrency-core-learning」
https://github.com/JeffLi1993/java-concurrency-core-learning
參考:
《Java并發(fā)編程的藝術(shù)》
《Java 7 并發(fā)編程實(shí)戰(zhàn)手冊》
《圖解 Java 多線程設(shè)計(jì)模式》