最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文詳解如何在Java中啟動(dòng)線程

 更新時(shí)間:2024年07月10日 08:58:47   作者:老譚說(shuō)架構(gòu)  
今天要跟大家聊一聊Java多線程的原理和使用方式,Java多線程是提高程序性能的重要機(jī)制,了解線程生命周期、同步機(jī)制、線程池和線程間通信等概念,可以幫助我們編寫(xiě)出高效、可靠的多線程程序,需要的朋友可以參考下

1. 簡(jiǎn)介

今天要跟大家聊一聊Java多線程的原理和使用方式,Java多線程是提高程序性能的重要機(jī)制。了解線程生命周期、同步機(jī)制、線程池和線程間通信等概念,可以幫助我們編寫(xiě)出高效、可靠的多線程程序。

Java 線程的生命周期可以分為以下幾個(gè)狀態(tài):

1. 新建 (New):  當(dāng)使用 new Thread() 創(chuàng)建線程對(duì)象時(shí),線程處于新建狀態(tài)。此時(shí)線程尚未啟動(dòng),還沒(méi)有分配系統(tǒng)資源。

2. 就緒 (Runnable):  當(dāng)調(diào)用線程對(duì)象的 start() 方法時(shí),線程進(jìn)入就緒狀態(tài)。此時(shí)線程已準(zhǔn)備好運(yùn)行,但尚未獲得 CPU 時(shí)間片,需要等待操作系統(tǒng)分配。

3. 運(yùn)行 (Running):  線程獲得 CPU 時(shí)間片,開(kāi)始執(zhí)行線程體代碼,進(jìn)入運(yùn)行狀態(tài)。

4. 阻塞 (Blocked):  當(dāng)線程遇到以下情況時(shí),會(huì)進(jìn)入阻塞狀態(tài):

  • 等待 (Waiting):  線程調(diào)用 Object.wait() 方法等待某個(gè)特定事件發(fā)生。
  • 睡眠 (Sleeping):  線程調(diào)用 Thread.sleep() 方法進(jìn)入睡眠狀態(tài),等待一段時(shí)間后自動(dòng)恢復(fù)運(yùn)行。
  • I/O 阻塞:  線程等待 I/O 操作完成,例如讀取文件或網(wǎng)絡(luò)數(shù)據(jù)。
  • 鎖阻塞:  線程試圖獲取某個(gè)鎖,但鎖被其他線程占用,導(dǎo)致阻塞。

5. 終止 (Terminated):  線程執(zhí)行完 run() 方法中的代碼,或者遇到異常而退出,進(jìn)入終止?fàn)顟B(tài)。

線程狀態(tài)轉(zhuǎn)換:

  • 新建 -> 就緒: 調(diào)用 start() 方法。
  • 就緒 -> 運(yùn)行: 操作系統(tǒng)分配 CPU 時(shí)間片。
  • 運(yùn)行 -> 阻塞: 線程遇到等待、睡眠、I/O 阻塞、鎖阻塞等情況。
  • 阻塞 -> 就緒: 等待的事件發(fā)生、睡眠時(shí)間結(jié)束、I/O 操作完成、獲得鎖。
  • 運(yùn)行 -> 終止: run() 方法執(zhí)行完畢、遇到異常。

其他重要概念:

  • 守護(hù)線程 (Daemon Thread):  守護(hù)線程是為其他線程服務(wù)的線程,例如垃圾回收線程。當(dāng)所有非守護(hù)線程都終止后,守護(hù)線程也會(huì)自動(dòng)終止。
  • 線程優(yōu)先級(jí) (Thread Priority):  線程可以設(shè)置優(yōu)先級(jí),優(yōu)先級(jí)高的線程更容易獲得 CPU 時(shí)間片。

2. 運(yùn)行線程的基礎(chǔ)知識(shí)

我們可以利用Thread框架輕松的編寫(xiě)一些在并行線程中運(yùn)行的邏輯。

讓我們嘗試一個(gè)基本的例子,通過(guò)擴(kuò)展Thread類(lèi):

public class NewThread extends Thread {
    public void run() {
        long startTime = System.currentTimeMillis();
        int i = 0;
        while (true) {
            System.out.println(this.getName() + ": New Thread is running..." + i++);
            try {
                //Wait for one sec so it doesn't print too fast
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ...
        }
    }
}

現(xiàn)在我們編寫(xiě)第二個(gè)類(lèi)來(lái)初始化并啟動(dòng)我們的線程:

public class SingleThreadExample {
    public static void main(String[] args) {
        NewThread t = new NewThread();
        t.start();
    }
}

我們應(yīng)該 對(duì)處于NEW狀態(tài)(相當(dāng)于未啟動(dòng))的線程 調(diào)用start()方法。否則,Java 將拋出IllegalThreadStateException異常的實(shí)例。

現(xiàn)在假設(shè)我們需要啟動(dòng)多個(gè)線程:

public class MultipleThreadsExample {
    public static void main(String[] args) {
        NewThread t1 = new NewThread();
        t1.setName("MyThread-1");
        NewThread t2 = new NewThread();
        t2.setName("MyThread-2");
        t1.start();
        t2.start();
    }
}

我們的代碼看起來(lái)仍然非常簡(jiǎn)單并且與我們?cè)诰W(wǎng)上找到的示例非常相似。

當(dāng)然,這與可用于生產(chǎn)的代碼還相去甚遠(yuǎn),以正確的方式管理資源至關(guān)重要,以避免過(guò)多的上下文切換或過(guò)多的內(nèi)存使用。

因此,為了做好生產(chǎn)準(zhǔn)備,我們現(xiàn)在需要編寫(xiě)額外的樣板來(lái)處理:

  • 持續(xù)創(chuàng)建新線程
  • 并發(fā)活動(dòng)線程數(shù)
  • 線程釋放:對(duì)于守護(hù)線程來(lái)說(shuō)非常重要,可以避免泄漏

如果我們?cè)敢猓覀兛梢詾樗羞@些情況甚至更多情況編寫(xiě)自己的代碼,但我們?yōu)槭裁匆匦掳l(fā)明輪子呢?

3. ExecutorService框架

ExecutorService實(shí)現(xiàn)了線程池設(shè)計(jì)模式(也稱(chēng)為復(fù)制工作器或工作組模型),并負(fù)責(zé)我們上面提到的線程管理,此外它還添加了一些非常有用的功能,如線程可重用性和任務(wù)隊(duì)列 。

線程可重用性尤其重要:在大型應(yīng)用程序中,分配和釋放許多線程對(duì)象會(huì)產(chǎn)生大量?jī)?nèi)存管理開(kāi)銷(xiāo)。

利用工作線程,我們可以最大限度地減少線程創(chuàng)建造成的開(kāi)銷(xiāo)。 為了簡(jiǎn)化池配置,ExecutorService帶有一個(gè)簡(jiǎn)單的構(gòu)造函數(shù)和一些自定義選項(xiàng),例如隊(duì)列的類(lèi)型、最小和最大線程數(shù)及其命名約定。

4. 使用執(zhí)行器啟動(dòng)任務(wù)

有了這個(gè)強(qiáng)大的框架,我們可以把思維從啟動(dòng)線程轉(zhuǎn)變?yōu)樘峤蝗蝿?wù)。

讓我們看看如何向執(zhí)行器提交異步任務(wù):

ExecutorService executor = Executors.newFixedThreadPool(10);
...
executor.submit(() -> {
    new Task();
});

我們可以使用兩種方法:execute(不返回任何內(nèi)容)和submit(返回封裝了計(jì)算結(jié)果的Future )。

5. 使用CompletableFutures啟動(dòng)任務(wù)

要從Future對(duì)象中檢索最終結(jié)果,我們可以使用 該對(duì)象中可用的get 方法,但這會(huì)阻塞父線程,直到計(jì)算結(jié)束。

或者,我們可以通過(guò)在任務(wù)中添加更多邏輯來(lái)避免阻塞,但我們必須增加代碼的復(fù)雜性。 Java 1.8 在Future構(gòu)造之上引入了一個(gè)新框架,以便更好地處理計(jì)算結(jié)果:CompletableFuture。

CompletableFuture 實(shí)現(xiàn)了CompletableStage,它增加了大量方法來(lái)附加回調(diào)并避免了在結(jié)果準(zhǔn)備好后運(yùn)行操作所需的所有管道。

提交任務(wù)的實(shí)現(xiàn)就簡(jiǎn)單多了:

CompletableFuture.supplyAsync(() -> "Hello");

supplyAsync接受一個(gè)Supplier,其中包含我們想要異步執(zhí)行的代碼——在我們的例子中是 lambda 參數(shù)。

該任務(wù)現(xiàn)在隱式提交給 ForkJoinPool.commonPool() ,或者我們可以指定我們喜歡的Executor作為第二個(gè)參數(shù)。

6. 運(yùn)行延遲或周期性任務(wù)

在處理復(fù)雜的 Web 應(yīng)用程序時(shí),我們可能需要在特定時(shí)間(或許是定期)運(yùn)行任務(wù)。

Java 有一些工具可以幫助我們運(yùn)行延遲或重復(fù)的操作:

  • 定時(shí)器
  • java.util.concurrent.ScheduledThreadPoolExecutor

6.1. 計(jì)時(shí)器

計(jì)時(shí)器是一種用于安排任務(wù)在后臺(tái)線程中將來(lái)執(zhí)行的工具。

任務(wù)可以被安排一次性執(zhí)行,或者定期重復(fù)執(zhí)行。

如果我們想在延遲一秒鐘后運(yùn)行任務(wù),讓我們看看代碼是什么樣的:

TimerTask task = new TimerTask() {
    public void run() {
        System.out.println("Task performed on: " + new Date() + "n" 
          + "Thread's name: " + Thread.currentThread().getName());
    }
};
Timer timer = new Timer("Timer");
long delay = 1000L;
timer.schedule(task, delay);復(fù)制

現(xiàn)在讓我們添加一個(gè)重復(fù)的計(jì)劃:

timer.scheduleAtFixedRate(repeatedTask, delay, period);復(fù)制

這一次,任務(wù)將在指定的延遲后運(yùn)行,并且在經(jīng)過(guò)一段時(shí)間后重復(fù)運(yùn)行。

6.2. ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor具有與 Timer類(lèi) 類(lèi)似的方法:

ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
ScheduledFuture<Object> resultFuture
  = executorService.schedule(callableTask, 1, TimeUnit.SECONDS);

為了結(jié)束我們的示例,我們使用 scheduleAtFixedRate() 來(lái)執(zhí)行重復(fù)任務(wù):

ScheduledFuture<Object> resultFuture
 = executorService.scheduleAtFixedRate(runnableTask, 100, 450, TimeUnit.MILLISECONDS);

上述代碼將在初始延遲 100 毫秒后執(zhí)行一項(xiàng)任務(wù),之后每 450 毫秒執(zhí)行一次相同的任務(wù)。

如果處理器不能在下一次發(fā)生之前及時(shí)完成處理任務(wù),則 ScheduledExecutorService 將等到當(dāng)前任務(wù)完成后再開(kāi)始下一個(gè)任務(wù)。

為了避免這段等待時(shí)間,我們可以使用 scheduleWithFixedDelay() ,正如其名稱(chēng)所述,它可以保證任務(wù)迭代之間的固定長(zhǎng)度延遲。

6.3. 哪個(gè)工具更好?

如果我們運(yùn)行上述例子,計(jì)算的結(jié)果看起來(lái)是一樣的。

那么, 我們?nèi)绾芜x擇正確的工具?

當(dāng)一個(gè)框架提供多種選擇時(shí),了解底層技術(shù)以做出明智的決定非常重要。

讓我們嘗試更深入地探究一下。

計(jì)時(shí)器:

  • 不提供實(shí)時(shí)保證:它使用 Object.wait  (long) 方法來(lái)安排任務(wù)
  • 只有一個(gè)后臺(tái)線程,因此任務(wù)按順序運(yùn)行,長(zhǎng)時(shí)間運(yùn)行的任務(wù)可能會(huì)延遲其他任務(wù)
  • TimerTask中拋出的運(yùn)行時(shí)異常會(huì)殺死唯一可用的線程,從而殺死Timer

ScheduledThreadPoolExecutor:

  • 可以配置任意數(shù)量的線程
  • 可以利用所有可用的 CPU 核心
  • 捕獲運(yùn)行時(shí)異常并讓我們根據(jù)需要處理它們(通過(guò)重寫(xiě)ThreadPoolExecutor的 afterExecute方法)**
  • 取消引發(fā)異常的任務(wù),同時(shí)讓其他任務(wù)繼續(xù)運(yùn)行
  • 依靠操作系統(tǒng)調(diào)度系統(tǒng)來(lái)跟蹤時(shí)區(qū)、延遲、太陽(yáng)時(shí)等。
  • 如果我們需要多個(gè)任務(wù)之間的協(xié)調(diào),則提供協(xié)作 API,例如等待所有提交的任務(wù)完成
  • 提供更好的 API 來(lái)管理線程生命周期

7. Future和ScheduledFuture之間的區(qū)別

在我們的代碼示例中,我們可以觀察到ScheduledThreadPoolExecutor 返回特定類(lèi)型的Future:ScheduledFuture。

ScheduledFuture 擴(kuò)展了Future和Delayed接口,因此繼承了額外的方法getDelay  ,該方法返回與當(dāng)前任務(wù)相關(guān)的剩余延遲。它由RunnableScheduledFuture擴(kuò)展,并添加了一個(gè)方法來(lái)檢查任務(wù)是否是周期性的。

ScheduledThreadPoolExecutor 通過(guò)內(nèi)部類(lèi)ScheduledFutureTask實(shí)現(xiàn)所有這些構(gòu)造,并使用它們來(lái)控制任務(wù)生命周期。

8. 結(jié)論

Java 多線程在各種應(yīng)用場(chǎng)景中都發(fā)揮著重要作用,可以顯著提高程序效率和響應(yīng)速度。以下列舉一些常見(jiàn)的 Java 多線程使用場(chǎng)景:

1. 并發(fā)處理:

  • 網(wǎng)絡(luò)應(yīng)用程序:  多個(gè)線程可以同時(shí)處理來(lái)自多個(gè)客戶(hù)端的請(qǐng)求,提高服務(wù)器的吞吐量和響應(yīng)速度。
  • 文件處理:  多個(gè)線程可以同時(shí)讀取、寫(xiě)入或處理多個(gè)文件,加速文件操作。
  • 數(shù)據(jù)庫(kù)操作:  多個(gè)線程可以同時(shí)執(zhí)行數(shù)據(jù)庫(kù)查詢(xún)或更新操作,提高數(shù)據(jù)庫(kù)的并發(fā)性能。

2. 用戶(hù)界面響應(yīng):

  • 圖形界面應(yīng)用程序:  多個(gè)線程可以將耗時(shí)的操作(如圖片加載、數(shù)據(jù)處理)放到后臺(tái)執(zhí)行,避免阻塞主線程,保持用戶(hù)界面的流暢響應(yīng)。
  • 游戲開(kāi)發(fā):  多個(gè)線程可以同時(shí)處理游戲邏輯、渲染圖形、播放聲音等任務(wù),提高游戲流暢度和響應(yīng)速度。

3. 并行計(jì)算:

  • 科學(xué)計(jì)算:  多個(gè)線程可以同時(shí)執(zhí)行復(fù)雜的數(shù)學(xué)計(jì)算,加速計(jì)算過(guò)程。
  • 數(shù)據(jù)分析:  多個(gè)線程可以同時(shí)處理大量數(shù)據(jù),加快數(shù)據(jù)分析速度。
  • 機(jī)器學(xué)習(xí):  多個(gè)線程可以同時(shí)訓(xùn)練模型,提高模型訓(xùn)練效率。

4. 任務(wù)調(diào)度:

  • 任務(wù)管理系統(tǒng):  多個(gè)線程可以同時(shí)執(zhí)行不同的任務(wù),提高任務(wù)處理效率。
  • 定時(shí)任務(wù):  多個(gè)線程可以按照指定的時(shí)間間隔或時(shí)間點(diǎn)執(zhí)行任務(wù)。

5. 異步操作:

  • 網(wǎng)絡(luò)通信:  使用多線程可以異步發(fā)送和接收網(wǎng)絡(luò)數(shù)據(jù),提高網(wǎng)絡(luò)通信效率。
  • 文件上傳/下載:  多線程可以異步執(zhí)行文件上傳/下載操作,避免阻塞主線程。

6. 其他應(yīng)用場(chǎng)景:

  • 多線程測(cè)試:  可以使用多線程模擬多個(gè)用戶(hù)同時(shí)訪問(wèn)系統(tǒng),進(jìn)行壓力測(cè)試。
  • 并發(fā)編程框架:  許多并發(fā)編程框架(如 Akka、RxJava)都是基于多線程實(shí)現(xiàn)的。

以上就是一文詳解如何在Java中啟動(dòng)線程的詳細(xì)內(nèi)容,更多關(guān)于Java啟動(dòng)線程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java線程優(yōu)先級(jí)和守護(hù)線程原理解析

    Java線程優(yōu)先級(jí)和守護(hù)線程原理解析

    這篇文章主要介紹了Java線程優(yōu)先級(jí)和守護(hù)線程原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • 基于Spring Boot 的小區(qū)人臉識(shí)別與出入記錄管理系統(tǒng)功能

    基于Spring Boot 的小區(qū)人臉識(shí)別與出入記錄管理系統(tǒng)功能

    文章介紹基于SpringBoot框架與百度AI人臉識(shí)別API的小區(qū)出入管理系統(tǒng),實(shí)現(xiàn)自動(dòng)識(shí)別、記錄及查詢(xún)功能,涵蓋技術(shù)選型、數(shù)據(jù)模型設(shè)計(jì)、接口開(kāi)發(fā)與系統(tǒng)優(yōu)化方案,為智慧社區(qū)提供高效安全管理工具,感興趣的朋友跟隨小編一起看看吧
    2025-08-08
  • MyBatis-Plus中如何實(shí)現(xiàn)動(dòng)態(tài)表名

    MyBatis-Plus中如何實(shí)現(xiàn)動(dòng)態(tài)表名

    這篇文章主要介紹了MyBatis-Plus中如何實(shí)現(xiàn)動(dòng)態(tài)表名問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • SpringBoot中ApplicationEvent的使用步驟詳解

    SpringBoot中ApplicationEvent的使用步驟詳解

    ApplicationEvent類(lèi)似于MQ,是Spring提供的一種發(fā)布訂閱模式的事件處理方式,本文給大家介紹SpringBoot中ApplicationEvent的使用步驟詳解,感興趣的朋友跟隨小編一起看看吧
    2024-04-04
  • 淺談Strut2如何對(duì)請(qǐng)求參數(shù)的封裝

    淺談Strut2如何對(duì)請(qǐng)求參數(shù)的封裝

    這篇文章主要介紹了淺談Strut2如何對(duì)請(qǐng)求參數(shù)的封裝,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2017-12-12
  • java實(shí)現(xiàn)單鏈表中是否有環(huán)的方法詳解

    java實(shí)現(xiàn)單鏈表中是否有環(huán)的方法詳解

    本篇文章介紹了,用java實(shí)現(xiàn)單鏈表中是否有環(huán)的方法詳解。需要的朋友參考下
    2013-05-05
  • SpringBoot+MyBatis Plus實(shí)現(xiàn)用戶(hù)登錄認(rèn)證

    SpringBoot+MyBatis Plus實(shí)現(xiàn)用戶(hù)登錄認(rèn)證

    本文介紹了使用Spring Boot和MyBatis Plus實(shí)現(xiàn)用戶(hù)登錄認(rèn)證功能的完整流程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-09-09
  • Spring boot實(shí)現(xiàn)上傳文件到本地服務(wù)器

    Spring boot實(shí)現(xiàn)上傳文件到本地服務(wù)器

    這篇文章主要為大家詳細(xì)介紹了Spring boot實(shí)現(xiàn)上傳文件到本地服務(wù)器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • java基礎(chǔ)的詳細(xì)了解第八天

    java基礎(chǔ)的詳細(xì)了解第八天

    這篇文章對(duì)Java編程語(yǔ)言的基礎(chǔ)知識(shí)作了一個(gè)較為全面的匯總,在這里給大家分享一下。需要的朋友可以參考,希望能給你帶來(lái)幫助
    2021-08-08
  • SpringBoot讀取yaml文件操作詳解

    SpringBoot讀取yaml文件操作詳解

    YAML 是 “YAML Ain’t Markup Language”(YAML 不是一種標(biāo)記語(yǔ)言)的遞歸縮寫(xiě)。在開(kāi)發(fā)的這種語(yǔ)言時(shí),YAML 的意思其實(shí)是:“Yet Another Markup Language”(仍是一種標(biāo)記語(yǔ)言),本文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-09-09

最新評(píng)論

诏安县| 玉屏| 大连市| 余干县| 潞城市| 西藏| 洛浦县| 寻甸| 余庆县| 临高县| 井冈山市| 安陆市| 洪洞县| 兴海县| 临桂县| 锡林浩特市| 高陵县| 昌乐县| 五原县| 临邑县| 武威市| 周口市| 泽普县| 东乌珠穆沁旗| 台北市| 临武县| 延长县| 满洲里市| 简阳市| 库车县| 深州市| 逊克县| 衡阳县| 普安县| 隆德县| 霍州市| 阳曲县| 河曲县| 东至县| 莱芜市| 扎囊县|