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

Java中控制多線程順序執(zhí)行的六種實現(xiàn)方案

 更新時間:2025年09月14日 14:33:58   作者:Bug改不動了  
在多線程編程中,線程的執(zhí)行順序本質(zhì)上是不確定的,由操作系統(tǒng)調(diào)度器決定,但在某些業(yè)務場景中,我們需要確保線程按照特定順序執(zhí)行,所以本文介紹了Java中控制多線程順序執(zhí)行的六種實現(xiàn)方案,需要的朋友可以參考下

一、線程順序執(zhí)行的核心挑戰(zhàn)

在多線程編程中,線程的執(zhí)行順序本質(zhì)上是不確定的,由操作系統(tǒng)調(diào)度器決定。但在某些業(yè)務場景中,我們需要確保線程按照特定順序執(zhí)行,例如:

  1. 分階段任務處理(先初始化,再加載,最后執(zhí)行)
  2. 事件的有序處理(保證事件處理的先后順序)
  3. 資源的有序訪問(避免競爭條件)

下面介紹的6種方法都能解決這個問題,但各有特點和適用場景。

二、6種實現(xiàn)方法詳解

方法1:join() - 簡單直接的阻塞方案

實現(xiàn)原理

join()方法會使當前線程等待目標線程執(zhí)行完畢。通過在主線程中依次調(diào)用各個線程的join(),可以實現(xiàn)嚴格的順序執(zhí)行。

public class JoinExample {
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            System.out.println("第一階段任務執(zhí)行");
            // 模擬任務執(zhí)行時間
            try { Thread.sleep(500); } catch (InterruptedException e) {}
        });
        
        Thread t2 = new Thread(() -> System.out.println("第二階段任務執(zhí)行"));
        Thread t3 = new Thread(() -> System.out.println("第三階段任務執(zhí)行"));
        
        try {
            System.out.println("啟動第一階段任務");
            t1.start();
            t1.join();  // 主線程在此等待t1完成
            
            System.out.println("啟動第二階段任務");
            t2.start();
            t2.join();  // 等待t2完成
            
            System.out.println("啟動第三階段任務");
            t3.start();
            t3.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.err.println("任務執(zhí)行被中斷");
        }
    }
}

優(yōu)點

  • 實現(xiàn)簡單直觀
  • 不需要額外同步工具

缺點

  • 會阻塞主線程
  • 不夠靈活,難以應對復雜場景

適用場景:簡單的線性任務流,且可以接受阻塞主線程的情況。

方法2:單線程線程池 - 優(yōu)雅的任務隊列方案

實現(xiàn)原理

通過Executors.newSingleThreadExecutor()創(chuàng)建單線程的線程池,自然保證任務按提交順序執(zhí)行。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SingleThreadExecutorExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        
        executor.execute(() -> {
            System.out.println("準備數(shù)據(jù)");
            // 模擬耗時操作
            try { Thread.sleep(1000); } catch (InterruptedException e) {}
        });
        
        executor.execute(() -> System.out.println("處理數(shù)據(jù)"));
        executor.execute(() -> System.out.println("保存結(jié)果"));
        
        executor.shutdown();
        
        // 等待所有任務完成
        while (!executor.isTerminated()) {}
        System.out.println("所有任務已完成");
    }
}

優(yōu)點

  • 自動管理線程生命周期
  • 支持任務隊列
  • 避免手動創(chuàng)建線程

缺點

  • 無法靈活控制中間狀態(tài)
  • 單線程可能成為性能瓶頸

適用場景:需要順序執(zhí)行但可能動態(tài)添加任務的場景。

方法3:CountDownLatch - 靈活的同步屏障方案

實現(xiàn)原理

CountDownLatch通過計數(shù)器實現(xiàn)線程等待,允許一個或多個線程等待其他線程完成操作。

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {
    public static void main(String[] args) {
        // 第一個閘門,初始為1表示t1可以直接執(zhí)行
        CountDownLatch latch1 = new CountDownLatch(1);
        // 第二個閘門,t2需要等待
        CountDownLatch latch2 = new CountDownLatch(1);
        
        Thread t1 = new Thread(() -> {
            System.out.println("數(shù)據(jù)庫連接建立");
            latch1.countDown(); // t1完成后打開閘門1
        });
        
        Thread t2 = new Thread(() -> {
            try {
                latch1.await(); // 等待閘門1打開
                System.out.println("查詢用戶數(shù)據(jù)");
                latch2.countDown(); // t2完成后打開閘門2
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        
        Thread t3 = new Thread(() -> {
            try {
                latch2.await(); // 等待閘門2打開
                System.out.println("生成報表");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        
        // 故意打亂啟動順序測試
        t3.start();
        t2.start();
        t1.start();
    }
}

優(yōu)點

  • 靈活控制多個線程的依賴關系
  • 支持一對多、多對多同步
  • 不阻塞主線程

缺點

  • 需要創(chuàng)建多個CountDownLatch對象
  • 計數(shù)器不可重置

適用場景:分階段任務,特別是多階段有復雜依賴關系的場景。

方法4:ReentrantLock與Condition - 精準控制的等待/通知機制

實現(xiàn)原理

ReentrantLock配合Condition提供了比synchronized更靈活的線程通信機制。每個Condition對象實質(zhì)上是一個獨立的等待隊列,可以實現(xiàn)精確的線程喚醒控制。

import java.util.concurrent.locks.*;

public class ReentrantLockConditionExample {
    // 可重入鎖
    private static Lock lock = new ReentrantLock(true); // 公平鎖
    // 三個條件變量
    private static Condition condition1 = lock.newCondition();
    private static Condition condition2 = lock.newCondition();
    private static Condition condition3 = lock.newCondition();
    // 狀態(tài)標志
    private static volatile int flag = 1;

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> task(1, 2, condition1, condition2));
        Thread t2 = new Thread(() -> task(2, 3, condition2, condition3));
        Thread t3 = new Thread(() -> task(3, 1, condition3, condition1));

        t1.start();
        t2.start();
        t3.start();

        // 模擬運行后停止
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.exit(0);
    }

    private static void task(int currentFlag, int nextFlag, 
                           Condition waitCondition, Condition signalCondition) {
        while (true) {
            lock.lock();
            try {
                // 檢查是否輪到自己執(zhí)行
                while (flag != currentFlag) {
                    waitCondition.await(); // 釋放鎖并等待
                }
                
                System.out.println("Thread " + currentFlag + " 正在執(zhí)行");
                Thread.sleep(1000); // 模擬處理時間
                
                // 更新狀態(tài)并喚醒下一個線程
                flag = nextFlag;
                signalCondition.signal();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                lock.unlock();
            }
        }
    }
}

關鍵點解析

  1. 公平鎖:構(gòu)造ReentrantLock時傳入true參數(shù)創(chuàng)建公平鎖,減少線程饑餓
  2. 條件變量:每個線程有自己專屬的Condition,避免無效喚醒
  3. volatile變量:確保狀態(tài)標志的可見性
  4. await/signal:精確控制線程的等待和喚醒

優(yōu)點

  • 最精確的線程控制能力
  • 支持公平性配置
  • 可中斷的等待機制
  • 支持多個等待條件

缺點

  • 實現(xiàn)復雜度高
  • 需要手動管理鎖的獲取和釋放
  • 容易遺漏unlock導致死鎖

適用場景

  • 需要精確控制線程執(zhí)行順序的復雜場景
  • 多條件等待的線程協(xié)作
  • 對公平性有要求的場景

方法5:Semaphore - 基于許可的同步控制

實現(xiàn)原理

Semaphore通過維護一組許可(permits)來控制線程訪問。初始化時指定許可數(shù)量,線程通過acquire()獲取許可,通過release()釋放許可。

import java.util.concurrent.Semaphore;

public class SemaphoreExample {
    // 初始化信號量:t1可以直接運行,t2和t3需要等待
    private static Semaphore s1 = new Semaphore(1);
    private static Semaphore s2 = new Semaphore(0);
    private static Semaphore s3 = new Semaphore(0);

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            try {
                s1.acquire(); // 獲取許可
                System.out.println("線程1:數(shù)據(jù)加載");
                Thread.sleep(1000);
                s2.release(); // 釋放t2的許可
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });

        Thread t2 = new Thread(() -> {
            try {
                s2.acquire();
                System.out.println("線程2:數(shù)據(jù)處理");
                Thread.sleep(1000);
                s3.release();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });

        Thread t3 = new Thread(() -> {
            try {
                s3.acquire();
                System.out.println("線程3:結(jié)果保存");
                Thread.sleep(1000);
                s1.release(); // 循環(huán)執(zhí)行時可重新開始
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });

        // 啟動線程
        t1.start();
        t2.start();
        t3.start();

        // 允許程序運行一段時間后退出
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

進階用法

  1. 公平模式new Semaphore(1, true)
  2. 批量獲取acquire(int permits)
  3. 非阻塞獲取tryAcquire()
  4. 超時控制tryAcquire(long timeout, TimeUnit unit)

優(yōu)點

  • 靈活控制并發(fā)度
  • 支持許可的申請和釋放
  • 可實現(xiàn)資源池等復雜模式

缺點

  • 需要仔細設計許可數(shù)量

方法6:CompletableFuture - 函數(shù)式異步編程

實現(xiàn)原理

CompletableFuture是Java 8引入的增強版Future,支持函數(shù)式編程風格的任務編排。通過thenRun、thenApply等方法鏈式組合多個異步任務。

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class CompletableFutureExample {
    public static void main(String[] args) {
        // 創(chuàng)建異步任務鏈
        CompletableFuture<Void> taskChain = CompletableFuture
            .runAsync(() -> {
                System.out.println("任務1:初始化系統(tǒng)");
                sleep(1000);
            })
            .thenRunAsync(() -> {
                System.out.println("任務2:加載配置");
                sleep(1500);
            })
            .thenRunAsync(() -> {
                System.out.println("任務3:啟動服務");
                sleep(500);
            })
            .thenRunAsync(() -> {
                System.out.println("任務4:運行監(jiān)控");
            });
        
        // 等待所有任務完成
        try {
            taskChain.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
    
    private static void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

優(yōu)點

  • 聲明式編程風格
  • 強大的任務組合能力
  • 內(nèi)置異常處理機制
  • 與現(xiàn)代Java特性完美集成

缺點

  • 學習曲線較陡峭
  • 調(diào)試相對困難
  • Java 8+才支持

適用場景

  • 現(xiàn)代Java應用開發(fā)
  • 復雜的異步任務編排
  • 需要組合多個異步結(jié)果的場景
  • 響應式編程基礎

三、常見問題與解決方案

Q1:為什么await()要在while循環(huán)中調(diào)用?

A:這是為了防止"虛假喚醒"(spurious wakeup),即線程可能在沒有收到通知的情況下被喚醒。while循環(huán)會重新檢查條件,確保條件真正滿足。

Q2:如何避免死鎖?

A:遵循以下原則:

  • 按固定順序獲取多個鎖
  • 設置鎖超時時間
  • 避免在鎖中調(diào)用外部方法
  • 使用tryLock()替代lock()

以上就是Java中控制多線程順序執(zhí)行的六種實現(xiàn)方案的詳細內(nèi)容,更多關于Java控制多線程順序執(zhí)行的資料請關注腳本之家其它相關文章!

相關文章

  • IDEA導入項目報錯java程序包不存在問題及解決

    IDEA導入項目報錯java程序包不存在問題及解決

    在IDEA導入項目時,若出現(xiàn)javafx包不存在錯誤,需檢查并更改為JDK1.8版本(原默認為JDK14),同時確保模塊目錄正確、Tomcat配置無誤,并補全JavaFX依賴,即可解決運行問題
    2025-09-09
  • 淺談Java字符串比較的三種方法

    淺談Java字符串比較的三種方法

    這篇文章主要介紹了淺談Java字符串比較的三種方法,字符串比較是常見的操作,包括比較相等、比較大小、比較前綴和后綴串等,需要的朋友可以參考下
    2023-04-04
  • SpringBoot后端實現(xiàn)小程序微信登錄功能實現(xiàn)

    SpringBoot后端實現(xiàn)小程序微信登錄功能實現(xiàn)

    微信小程序登錄是開發(fā)者通過微信提供的身份驗證機制,獲取用戶唯一標識(openid)和會話密鑰(session_key)的過程,這篇文章給大家介紹SpringBoot后端實現(xiàn)小程序微信登錄功能實現(xiàn),感興趣的朋友跟隨小編一起看看吧
    2025-05-05
  • SpringBoot WebSocket實時監(jiān)控異常的詳細流程

    SpringBoot WebSocket實時監(jiān)控異常的詳細流程

    最近做了一個需求,消防的設備巡檢,如果巡檢發(fā)現(xiàn)異常,通過手機端提交,后臺的實時監(jiān)控頁面實時獲取到該設備的信息及位置,然后安排員工去處理。這篇文章主要介紹了SpringBoot WebSocket實時監(jiān)控異常的全過程,感興趣的朋友一起看看吧
    2021-10-10
  • 使用Java 壓縮文件打包tar.gz 包的詳細教程

    使用Java 壓縮文件打包tar.gz 包的詳細教程

    本文帶領大家學習如何使用Java 壓縮文件打包tar.gz 包,主要通過 Apache compress 工具打包,通過示例代碼給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧
    2021-05-05
  • 從零搭建SpringBoot+MyBatisPlus快速開發(fā)腳手架

    從零搭建SpringBoot+MyBatisPlus快速開發(fā)腳手架

    這篇文章主要為大家介紹了從零搭建SpringBoot+MyBatisPlus快速開發(fā)腳手架示例教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • 使用Spring的FactoryBean創(chuàng)建和獲取Bean對象方式

    使用Spring的FactoryBean創(chuàng)建和獲取Bean對象方式

    這篇文章主要介紹了使用Spring的FactoryBean創(chuàng)建和獲取Bean對象方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • Nacos框架服務注冊實現(xiàn)流程

    Nacos框架服務注冊實現(xiàn)流程

    這篇文章主要介紹了SpringCloud服務注冊之nacos實現(xiàn)過程,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08
  • Activiti7與Spring以及Spring Boot整合開發(fā)

    Activiti7與Spring以及Spring Boot整合開發(fā)

    這篇文章主要介紹了Activiti7與Spring以及Spring Boot整合開發(fā),在Activiti中核心類的是ProcessEngine流程引擎,與Spring整合就是讓Spring來管理ProcessEngine,有感興趣的同學可以參考閱讀
    2023-03-03
  • servlet基礎知識_動力節(jié)點Java學院整理

    servlet基礎知識_動力節(jié)點Java學院整理

    這篇文章主要為大家詳細介紹了servlet基礎的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07

最新評論

富川| 鹤山市| 永仁县| 崇文区| 玛多县| 中牟县| 台北市| 堆龙德庆县| 岳普湖县| 平原县| 长顺县| 怀来县| 白沙| 平定县| 宁河县| 玉山县| 芷江| 裕民县| 哈密市| 祁东县| 天水市| 常州市| 新沂市| 易门县| 碌曲县| 五峰| 巨鹿县| 于田县| 台东市| 潮安县| 绥芬河市| 老河口市| 奉新县| 乐亭县| 陆河县| 铜梁县| 理塘县| 乌鲁木齐市| 新绛县| 平和县| 汝州市|