Java基礎(chǔ)夯實(shí)之線程問題全面解析
1. 線程是什么
操作系統(tǒng)支持多個(gè)應(yīng)用程序并發(fā)執(zhí)行,每個(gè)應(yīng)用程序至少對(duì)應(yīng)一個(gè)進(jìn)程 ,彼此之間的操作和數(shù)據(jù)不受干擾,彼此通信一般采用管道通信、消息隊(duì)列、共享內(nèi)存等方式。當(dāng)一個(gè)進(jìn)程需要磁盤IO的時(shí)候,CPU就切換到另外的進(jìn)程,提高了CPU利用率。
有了進(jìn)程,為什么還要線程?因?yàn)檫M(jìn)程的成本太高了。
啟動(dòng)新的進(jìn)程必須分配獨(dú)立的內(nèi)存空間,建立數(shù)據(jù)表維護(hù)它的代碼段、堆棧段和數(shù)據(jù)段,這是昂貴的多任務(wù)工作方式。線程可以看作輕量化的進(jìn)程。線程之間使用相同的地址空間,切換線程的時(shí)間遠(yuǎn)小于切換進(jìn)程的時(shí)間。
進(jìn)程是資源分配的最小單位,而線程是CPU調(diào)度的最小單位。每一個(gè)進(jìn)程中至少有一個(gè)線程,同一進(jìn)程的所有線程共享該進(jìn)程的所有資源,多個(gè)線程可以完成多個(gè)不同的任務(wù),也就是我們常說的并發(fā)多線程。
2. 怎樣創(chuàng)建線程
創(chuàng)建線程常用的有四種方式,分別是:
- 繼承Thread類
- 實(shí)現(xiàn)Runnable接口
- 實(shí)現(xiàn)Callable接口
- 使用線程池創(chuàng)建
分別看一下怎么具體怎么使用代碼創(chuàng)建的?
2.1 繼承Thread類
public class ThreadDemo { public static void main(String[] args) { Thread thread = new MyThread(); thread.start(); // 啟動(dòng)線程 } } class MyThread extends Thread { @Override public void run() { System.out.println("關(guān)注公眾號(hào):一燈架構(gòu)"); } }
輸出結(jié)果:
關(guān)注公眾號(hào):一燈架構(gòu)
start方法用來啟動(dòng)線程,只能被調(diào)用一次。
run方法是線程的核心方法,業(yè)務(wù)邏輯都寫在run方法中。
2.2 實(shí)現(xiàn)Runnable接口
public class ThreadDemo { public static void main(String[] args) { MyRunnable myRunnable = new MyRunnable(); Thread thread1 = new Thread(myRunnable, "線程1"); Thread thread2 = new Thread(myRunnable, "線程2"); thread1.start(); // 啟動(dòng)線程1 thread2.start(); // 啟動(dòng)線程2 } } class MyRunnable implements Runnable { private int count = 5; @Override public void run() { while (count > 0) { System.out.println(Thread.currentThread().getName() + ",關(guān)注公眾號(hào):一燈架構(gòu)," + count--); } } }
輸出結(jié)果:
線程2,關(guān)注公眾號(hào):一燈架構(gòu),4
線程1,關(guān)注公眾號(hào):一燈架構(gòu),5
線程1,關(guān)注公眾號(hào):一燈架構(gòu),2
線程1,關(guān)注公眾號(hào):一燈架構(gòu),1
線程2,關(guān)注公眾號(hào):一燈架構(gòu),3
需要把Runnable實(shí)例放到Thread類中,才能執(zhí)行,Thread對(duì)象才是真正的線程對(duì)象。
使用實(shí)現(xiàn)Runnable接口創(chuàng)建線程方式,相比繼承Thread類創(chuàng)建線程,優(yōu)點(diǎn)是:
- 實(shí)現(xiàn)的方式?jīng)]有類的單繼承性的局限性
- 實(shí)現(xiàn)的方式更適合來處理多個(gè)線程有共享數(shù)據(jù)的情況
2.3 實(shí)現(xiàn)Callable接口
public class ThreadTest { public static void main(String[] args) throws ExecutionException, InterruptedException { MyCallable myCallable = new MyCallable(); FutureTask<String> futureTask = new FutureTask<String>(myCallable); Thread thread = new Thread(futureTask); thread.start(); System.out.println(futureTask.get()); } } class MyCallable implements Callable { @Override public String call() throws Exception { return "關(guān)注公眾號(hào):一燈架構(gòu)"; } }
輸出結(jié)果:
關(guān)注公眾號(hào):一燈架構(gòu)
實(shí)現(xiàn)Callable接口的線程實(shí)例對(duì)象,配合FutureTask使用,可以接收返回值。
2.4 使用線程池創(chuàng)建
public class ThreadDemo { public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(10); executorService.execute(() -> System.out.println("關(guān)注公眾號(hào):一燈架構(gòu)")); } }
輸出結(jié)果:
關(guān)注公眾號(hào):一燈架構(gòu)
使用線程池創(chuàng)建線程是工作開發(fā)中最常用的方式,優(yōu)點(diǎn)是:
- 線程池幫忙管理對(duì)象的創(chuàng)建與銷毀,減輕開發(fā)者工作量
- 線程池幫忙管理任務(wù)的調(diào)用,資源的創(chuàng)建與分配
- 復(fù)用線程和對(duì)象,提高使用效率
3. 線程的狀態(tài)
線程共有6種狀態(tài),分別是NEW(初始化)、RUNNABLE(可運(yùn)行)、WAITING(等待)、TIMED_WAITING(超時(shí)等待)、BLOCKED(阻塞)、TERMINATED(終止)。
1.NEW(初始化)
表示創(chuàng)建線程對(duì)象之后,還沒有調(diào)用start方法。
2.RUNNABLE(可運(yùn)行)
表示調(diào)用start方法之后,等待CPU調(diào)度。為了便于理解,通常又把RUNNABLE分別RUNNING(運(yùn)行中)和READY(就緒)。處在RUNNING(運(yùn)行中)狀態(tài)的線程可以調(diào)用yield方法,讓出CPU時(shí)間片,然后跟其他處于READY(就緒)一起等待被調(diào)度。
3.WAITING(等待)
處于RUNNABLE狀態(tài)的線程調(diào)用wait方法之后,就處于等待狀態(tài),需要其他線程顯示地喚醒。
4.TIMED_WAITING(超時(shí)等待)
處于RUNNABLE狀態(tài)的線程調(diào)用wait(long)方法之后,就處于等待狀態(tài),需要其他線程顯示地喚醒。
5.BLOCKED(阻塞)
等待進(jìn)入synchronized方法/代碼塊,處于阻塞狀態(tài)。
6.TERMINATED(終止)
表示線程已經(jīng)執(zhí)行結(jié)束。
4. 線程常用方法
說一下線程有哪些常用的方法。
方法定義 | 含義 | 使用方式 |
---|---|---|
public synchronized void start() {……} | 啟動(dòng)線程 | MyThread myThread = new MyThread(); myThread.start(); |
public static native Thread currentThread(); | 獲取當(dāng)前線程實(shí)例對(duì)象 | Thread thread = Thread.currentThread(); |
public static native void yield(); | 讓出CPU時(shí)間片 | Thread.yield(); |
public static native void sleep(long millis); | 睡眠指定時(shí)間 | Thread.sleep(1L); |
public void interrupt() {……} | 中斷線程 | MyThread myThread = new MyThread(); myThread.interrupt(); |
public static boolean interrupted() {……} | 判斷線程是否已中斷 | MyThread myThread = new MyThread(); boolean interrupted = myThread.isInterrupted(); |
public final native boolean isAlive(); | 判斷線程是否是存活狀態(tài) | MyThread myThread = new MyThread(); boolean alive = myThread.isAlive(); |
public final String getName() {……} | 獲取線程名稱 | MyThread myThread = new MyThread(); String name = myThread.getName(); |
public State getState() {……} | 獲取線程狀態(tài) | MyThread myThread = new MyThread(); Thread.State state = myThread.getState(); |
public long getId() {……} | 獲取線程ID | MyThread myThread = new MyThread(); long id = myThread.getId(); |
public final void join() {……} | 等待其他線程執(zhí)行完再執(zhí)行 | MyThread myThread = new MyThread(); myThread.join(); |
以上就是Java基礎(chǔ)夯實(shí)之線程問題全面解析的詳細(xì)內(nèi)容,更多關(guān)于Java線程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaSwing坦克大戰(zhàn)游戲的設(shè)計(jì)和實(shí)現(xiàn)
JavaSwing坦克大戰(zhàn)游戲的設(shè)計(jì)要有圖形用戶界面,界面能夠反映游戲所有的細(xì)節(jié),在最終呈現(xiàn)的游戲中也要滿足所有需求,感興趣的小伙伴一起來看看吧2021-08-08java web在高并發(fā)和分布式下實(shí)現(xiàn)訂單號(hào)生成唯一的解決方案
這篇文章主要介紹了java web在高并發(fā)和分布式下實(shí)現(xiàn)訂單號(hào)生成唯一的解決方案,需要的朋友可以參考下2017-11-11SpringMVC中@RequestMapping注解用法實(shí)例
通過@RequestMapping注解可以定義不同的處理器映射規(guī)則,下面這篇文章主要給大家介紹了關(guān)于SpringMVC中@RequestMapping注解用法的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06基于JTable的列寬與內(nèi)容自適應(yīng)的實(shí)現(xiàn)方法
本篇文章是對(duì)JTable的列寬與內(nèi)容自適應(yīng)的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05Spring?boot?CommandLineRunner啟動(dòng)任務(wù)傳參實(shí)例詳解
在使用SpringBoot構(gòu)建項(xiàng)目時(shí),我們通常有一些預(yù)先數(shù)據(jù)的加載,下面這篇文章主要給大家介紹了關(guān)于Spring?boot?CommandLineRunner啟動(dòng)任務(wù)傳參的相關(guān)資料,需要的朋友可以參考下2022-06-06FastDFS分布式文件系統(tǒng)環(huán)境搭建及安裝過程解析
這篇文章主要介紹了FastDFS分布式文件系統(tǒng)環(huán)境搭建及安裝過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08java針對(duì)于時(shí)間轉(zhuǎn)換的DateUtils工具類
這篇文章主要為大家詳細(xì)介紹了java針對(duì)于時(shí)間轉(zhuǎn)換的DateUtils工具類,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12