一、狀態(tài)解讀

1、New 初始狀態(tài)
創(chuàng)建線(xiàn)程后,未運(yùn)行
2、Runnable 可運(yùn)行狀態(tài)
可能在運(yùn)行也可能在等待CPU時(shí)間片
同時(shí)也包含了操作系統(tǒng)線(xiàn)程的Ready 和 Running
著重說(shuō)一下Thread.yield():
Thread.yield()方法作用是:暫停當(dāng)前正在執(zhí)行的線(xiàn)程對(duì)象(及放棄當(dāng)前擁有的cup資源),并執(zhí)行其他線(xiàn)程。
yield()做的是讓當(dāng)前運(yùn)行線(xiàn)程回到可運(yùn)行狀態(tài),以允許具有相同優(yōu)先級(jí)的其他線(xiàn)程獲得運(yùn)行機(jī)會(huì)。因此,使用yield()的
目的是讓相同優(yōu)先級(jí)的線(xiàn)程之間能適當(dāng)?shù)妮嗈D(zhuǎn)執(zhí)行。但是,實(shí)際中無(wú)法保證yield()達(dá)到讓步目的,因?yàn)樽尣降木€(xiàn)程還有可能被
線(xiàn)程調(diào)度程序再次選中。
結(jié)論:yield()從未導(dǎo)致線(xiàn)程轉(zhuǎn)到等待/睡眠/阻塞狀態(tài)。在大多數(shù)情況下,yield()將導(dǎo)致線(xiàn)程從運(yùn)行狀態(tài)轉(zhuǎn)到可運(yùn)行狀態(tài),但有可能沒(méi)有效果。
3、Blocked 阻塞
等待獲取一個(gè)Synchronized鎖,如果搶占到鎖就會(huì)離開(kāi)此狀態(tài)。
4、Waiting 等待
等待其它線(xiàn)程顯示的喚醒,否則一直等待下去。
| 進(jìn)入 | 退出 |
|---|---|
沒(méi)有設(shè)置Time out參數(shù)的Object.wait() |
Object.notify() 或 Object.notifyAll() |
沒(méi)有設(shè)置Time out參數(shù)的Thread.join() |
被調(diào)用的線(xiàn)程執(zhí)行完畢 |
| LockSupport.park() | LockSupport.unpark(Thread thread) |
5、Timed Waiting 超時(shí)等待
| 進(jìn)入 | 退出 |
|---|---|
| Object.wait(Long) | Object.notify() 或 Object.notifyAll() |
| Thread.join(Long) | 超時(shí)退出 或 被調(diào)用的線(xiàn)程執(zhí)行完畢 |
| Thread.sleep(Long) | 超時(shí)退出 |
| LockSupport.parkNanos(Long) | LockSupport.unpark() |
| LockSupport.parkUntil(Long) | LockSupport.unpark() |
6、Terminated 終止?fàn)顟B(tài)
當(dāng)線(xiàn)程的run()方法執(zhí)行完畢或者主線(xiàn)程的main()方法完畢,就終止了,也許在這一刻,該線(xiàn)程還是存活的,但是它就要被終止了。
在一個(gè)終止的線(xiàn)程上調(diào)用start()方法會(huì)拋出異常java.lang.IllegalThreadStateException,線(xiàn)程一旦被終止,就無(wú)法再次運(yùn)行。
二、創(chuàng)建
Java線(xiàn)程的創(chuàng)建分為四種方式:
1)繼承Tread類(lèi)
public class MyThread extends Thread {
public void run() {
System.out.println("我是繼承于Thread的線(xiàn)程類(lèi)");
}
}
==================分割線(xiàn)====================
@Slf4j
public class JunitTest {
@Test
public void test() throws InterruptedException {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(3000);
}
}
繼承Thread類(lèi),重寫(xiě)其run()方法,然后通過(guò)start()方法調(diào)用即可,如果直接調(diào)用run()方法,那么就相當(dāng)于調(diào)用同步方法,只有調(diào)用start()才是啟動(dòng)線(xiàn)程的正解。
2)實(shí)現(xiàn)Runnable接口
public class MyThread implements Runnable {
@Override
public void run() {
System.out.println("我是實(shí)現(xiàn)Runnable接口的線(xiàn)程類(lèi)");
}
}
==================分割線(xiàn)====================
@Slf4j
public class JunitTest {
@Test
public void test() throws InterruptedException {
MyThread myThread = new MyThread();
// 傳入MyThread實(shí)例
Thread thread = new Thread(myThread);
thread.start();
Thread.sleep(3000);
}
}
實(shí)現(xiàn)Runnable接口,重寫(xiě)其run()方法。
限于第一種方式,受繼承的限制,第二種比第一種方式能好一些
3)實(shí)現(xiàn)Callable接口
public class MyThread implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("我是實(shí)現(xiàn)Callable接口的線(xiàn)程類(lèi)");
return "ok";
}
}
==================分割線(xiàn)====================
@Test
public void test() throws Exception {
Callable<String> callable = new MyThread();
FutureTask<String> futureTask = new FutureTask<>(callable);
Thread thread = new Thread(futureTask);
thread.start();
Thread.sleep(3000);
}
覆寫(xiě)call()方法,且支持返回值!
4)通過(guò)線(xiàn)程池
可以通過(guò)Executors來(lái)創(chuàng)建幾種不同類(lèi)型的線(xiàn)程池。Executors是一個(gè)線(xiàn)程池工廠,提供了創(chuàng)建線(xiàn)程池的很多方法。
1)SingleThreadPoolExecutor
只有一個(gè)線(xiàn)程的線(xiàn)程池。多個(gè)任務(wù)被提交到該線(xiàn)程池,先被緩存到隊(duì)列(隊(duì)列長(zhǎng)度為Integer.MAX_VALUE),按照FIFO先進(jìn)先出的原則進(jìn)行任務(wù)處理。
2)FixedThreadPool
固定大小的線(xiàn)程池,內(nèi)部存儲(chǔ)的線(xiàn)程數(shù)量是固定的,和上面的處理流程極為類(lèi)似,但是該線(xiàn)程池可以處理多個(gè)任務(wù),多個(gè)任務(wù)被提交到線(xiàn)程池,按照以下過(guò)程進(jìn)行處理:
1)如果線(xiàn)程的數(shù)量未達(dá)到設(shè)置的數(shù)量,線(xiàn)程池會(huì)創(chuàng)建線(xiàn)程來(lái)處理任務(wù)。
2)如果線(xiàn)程池里的線(xiàn)程數(shù)量達(dá)到了設(shè)置的數(shù)量,則取出空閑的線(xiàn)程執(zhí)行任務(wù)
3)如果沒(méi)有空閑線(xiàn)程,則將任務(wù)緩存到隊(duì)列(隊(duì)列長(zhǎng)度為Integer.MAX_VALUE),當(dāng)有空閑線(xiàn)程時(shí),按照FIFO的原則進(jìn)行任務(wù)處理
嚴(yán)格按照 1 -> 2 -> 3的過(guò)程進(jìn)行處理。
3)CachedThreadPool
創(chuàng)建帶緩存的線(xiàn)程池,這種線(xiàn)程池可以回收空閑線(xiàn)程,當(dāng)任務(wù)到達(dá)后,直接使用空閑線(xiàn)程,沒(méi)有空閑線(xiàn)程時(shí),新建線(xiàn)程。線(xiàn)程池核心長(zhǎng)度為0,最大長(zhǎng)度為Integer.MAX_VALUE。
用戶(hù)可以傳入線(xiàn)程池的核心線(xiàn)程數(shù)(最小線(xiàn)程數(shù)),最大線(xiàn)程數(shù)量,保持時(shí)間,時(shí)間單位,阻塞隊(duì)列這些參數(shù),最大線(xiàn)程數(shù)設(shè)置為jvm可用的cpu數(shù)為宜。
4)ScheduledThreadPool
一個(gè)可定期或者延時(shí)執(zhí)行任務(wù)的線(xiàn)程池
5) WorkStealingPool
創(chuàng)建擁有足夠線(xiàn)程數(shù)的線(xiàn)程池來(lái)維持相應(yīng)的并行級(jí)別,通過(guò)使用隊(duì)列來(lái)減少競(jìng)爭(zhēng),默認(rèn)為CPU的數(shù)量。它會(huì)通過(guò)工作竊取的方式,使得多核CPU不會(huì)閑置,總會(huì)有活著的線(xiàn)程讓CPU去運(yùn)行。
所謂工作竊取,指的是閑置的線(xiàn)程去處理本不屬于它的任務(wù)。
三
在實(shí)際項(xiàng)目里,我們很少成規(guī)模的手動(dòng)創(chuàng)建線(xiàn)程,一般都是使用線(xiàn)程池(池技術(shù))將線(xiàn)程的創(chuàng)建、銷(xiāo)毀、保留及其它管理工作交給線(xiàn)程池,用戶(hù)無(wú)需知道其內(nèi)部細(xì)節(jié),即可使用。