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

一文詳解如何在Java中啟動線程

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

1. 簡介

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

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

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

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

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

4. 阻塞 (Blocked):  當線程遇到以下情況時,會進入阻塞狀態(tài):

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

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

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

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

其他重要概念:

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

2. 運行線程的基礎(chǔ)知識

我們可以利用Thread框架輕松的編寫一些在并行線程中運行的邏輯。

讓我們嘗試一個基本的例子,通過擴展Thread類:

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)在我們編寫第二個類來初始化并啟動我們的線程:

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

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

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

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();
    }
}

我們的代碼看起來仍然非常簡單并且與我們在網(wǎng)上找到的示例非常相似。

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

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

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

如果我們愿意,我們可以為所有這些情況甚至更多情況編寫自己的代碼,但我們?yōu)槭裁匆匦掳l(fā)明輪子呢?

3. ExecutorService框架

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • 定時器
  • java.util.concurrent.ScheduledThreadPoolExecutor

6.1. 計時器

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

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

如果我們想在延遲一秒鐘后運行任務(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)在讓我們添加一個重復(fù)的計劃:

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

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

6.2. ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor具有與 Timer類 類似的方法:

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

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

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

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

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

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

6.3. 哪個工具更好?

如果我們運行上述例子,計算的結(jié)果看起來是一樣的。

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

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

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

計時器:

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

ScheduledThreadPoolExecutor:

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

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

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

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

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

8. 結(jié)論

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

1. 并發(fā)處理:

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

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

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

3. 并行計算:

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

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

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

5. 異步操作:

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

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

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

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

相關(guān)文章

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

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

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

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

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

    MyBatis-Plus中如何實現(xiàn)動態(tài)表名

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

    SpringBoot中ApplicationEvent的使用步驟詳解

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

    淺談Strut2如何對請求參數(shù)的封裝

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

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

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

    SpringBoot+MyBatis Plus實現(xiàn)用戶登錄認證

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

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

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

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

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

    SpringBoot讀取yaml文件操作詳解

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

最新評論

渝中区| 静宁县| 溆浦县| 深泽县| 抚顺市| 乡宁县| 花莲县| 海宁市| 海宁市| 白城市| 香港 | 杭锦旗| 阜南县| 长沙县| 孟州市| 治多县| 明水县| 龙里县| 麻栗坡县| 柳林县| 高碑店市| 博客| 祁门县| 泰安市| 金沙县| 马山县| 息烽县| 九龙坡区| 荆门市| 渝中区| 雷山县| 三门县| 平遥县| 石棉县| 安图县| 米脂县| 封丘县| 方城县| 呈贡县| 顺义区| 永福县|