面了個 5 年 Java,兩個線程進行數據交換都不會,我真是醉了。。

来源:https://www.cnblogs.com/javastack/archive/2022/06/10/16363358.html
-Advertisement-
Play Games

面試總結 最近棧長面試了一個 5 年經驗的 Java 程式員,簡歷和個人介紹都提到了精通 Java 多線程,於是我就問了幾個多線程方面的問題: 1、實現多線程有哪幾種方式,如何返回結果? 2、多個線程如何實現順序訪問? 3、兩個線程如何進行數據交換? 4、如何統計 5 個線程的運行總耗時? 5、如何 ...


面試總結

最近棧長面試了一個 5 年經驗的 Java 程式員,簡歷和個人介紹都提到了精通 Java 多線程,於是我就問了幾個多線程方面的問題:

1、實現多線程有哪幾種方式,如何返回結果?

2、多個線程如何實現順序訪問?

3、兩個線程如何進行數據交換?

4、如何統計 5 個線程的運行總耗時?

5、如何將一個任務拆分成多個子任務執行,最後合併結果?

大概問了他這幾個問題,答的並不是太好,3、4、5 題都沒有真正答上來,其實這幾個問題在 JDK 包中都有答案,但他給的是他個人臨時思考的方案,而且我個人覺得可能行不通。

工作 5 年了,這幾個題都答不好,有點說不過去,我真是醉了。。

其中,1、2、4、5 題我都在公眾號Java技術棧分享過相關的教程,也都在Java面試庫小程式上整理好了,最近面試的看看,今天就分享一下第 3 題的參考答案。

第 3 題也是通過 JDK 中的 java.util.concurrent.Exchanger 類來實現的,並不需要我們重覆造輪子,這個工具類在 JDK 1.5 中就已經引入了,並不是什麼 "新特性"。

Exchanger 簡介

Exchanger 就是線程之間的數據交換器,只能用於兩個線程之間的數據交換。

Exchanger 提供了兩個公開方法:

1、只帶泛型 V(交換的數據對象)的方法,線程一直阻塞,直到其他任意線程和它交換數據,或者被線程中斷;線程中斷也是一門學問,棧長在公眾號Java技術棧已經分享過,可在公眾號搜索閱讀;

2、另外一個帶時間的方法,如果超過設置時間還沒有線程和它交換數據,就會拋出 TimeoutException 異常;

Exchanger 實戰

簡單數據交換

來一個兩個線程正常數據交換的簡單示例:

private static void test1() {
    Exchanger exchanger = new Exchanger();

    new Thread(() -> {
        try {
            Object data = "-公眾號Java技術棧AAA";
            System.out.println(Thread.currentThread().getName() + data);

            // 開始交換數據
            data = exchanger.exchange(data);
            System.out.println(Thread.currentThread().getName() + data);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }).start();

    new Thread(() -> {
        try {
            Object data = "-公眾號Java技術棧BBB";
            System.out.println(Thread.currentThread().getName() + data);

            // 開始交換數據
            data = exchanger.exchange(data);
            System.out.println(Thread.currentThread().getName() + data);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }).start();
}

這段代碼的邏輯:

1、創建並啟動兩個線程;

2、進行數據交換前先列印出自己線程的數據;

3、進行數據交換;

4、列印數據交換之後的數據;

輸出結果:

從結果可以看出,線程 0、1 分別先列印出 A、B,數據交換之後,列印出了 B、A,數據交換正常!

超時數據交換

上面演示了兩個線程的正常交換,下麵再來一個帶超時的示例:

private static void test2() {
    Exchanger exchanger = new Exchanger();

    new Thread(() -> {
        try {
            Object data = "-公眾號Java技術棧AAA";
            System.out.println(Thread.currentThread().getName() + data);

            // 開始交換數據
            data = exchanger.exchange(data, 3000L, TimeUnit.MILLISECONDS);
            System.out.println(Thread.currentThread().getName() + data);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }).start();
}

現在只啟動了一個線程,並且設置了超時時間 3 秒。

輸出結果:

首先線程輸出了自己的數據,然後 3 秒後,並沒有其他線程和它交換數據,所以拋出了超時異常,最後線程結束運行。

本文所有案例源代碼已經上傳:https://github.com/javastacks/javastack

中斷數據交換

線程開始交換數據後,會一直阻塞直到其他任意線程和它交換數據,或者被中斷、超時,上面演示了超時,下麵這個示例演示一下中斷。

private static void test3() {
    Exchanger exchanger = new Exchanger();

    new Thread(() -> {
        try {
            Object data = "-公眾號Java技術棧AAA";
            System.out.println(Thread.currentThread().getName() + data);

            // 開始交換數據
            data = exchanger.exchange(data);
            System.out.println(Thread.currentThread().getName() + data);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }).start();
}

結果輸出:

預設情況下不帶超時設置會一直阻塞運行中……

現在我再加入一段中斷的邏輯:

private static void test3() throws InterruptedException {
    Exchanger exchanger = new Exchanger();

    Thread thread = new Thread(() -> {
        try {
            Object data = "-公眾號Java技術棧AAA";
            System.out.println(Thread.currentThread().getName() + data);

            // 開始交換數據
            data = exchanger.exchange(data);
            System.out.println(Thread.currentThread().getName() + data);
        } catch (Exception e) {
            e.printStackTrace();
        }
    });

    thread.start();

    // 線程中斷
    Thread.sleep(3000L);
    thread.interrupt();
}

主線程休眠 3 秒後,中斷該線程。

輸出結果:

輸出結果 3 秒後,線程被中斷了,拋出了中斷異常,線程也停止阻塞,最後線程結束運行。

兩兩數據交換

另外需要知道是,Exchanger 只能用於兩個線程之間的數據交換,一個線程開啟數據交換之後,會阻塞直到其他任意線程同樣開啟數據交換達到交換點。

最後來個示例,開啟 10 個線程,看它們是怎麼兩兩交換的:

private static void test4() {
    Exchanger exchanger = new Exchanger();

    for (int i = 1; i <= 10; i++) {
        Integer data = i;
        new Thread(() -> {
            try {
                Object exchange = exchanger.exchange(data);
                System.out.println(Thread.currentThread().getName() + "-" + exchange);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "Java技術棧" + i).start();
    }
}

輸出結果:

可以看到,10 個線程,都兩兩交換彼此的數據了。

總結

本文介紹了線程之間的數據交換器 Exchanger 類的使用,只能用於多個線程中的兩個線程兩兩交換數據,如果沒有對應的線程交換就會一直阻塞,可設置超時,可以中斷。

你都掌握了嗎?面試如果問到,你需要掌握這個類的用法,當然也有其他的方案,但如果不是必須就沒有必要重覆造輪子,重覆造輪子需要考慮的面更多。

本文所有案例源代碼已經上傳:

https://github.com/javastacks/javastack

歡迎 Star 學習,後面 Java 示例都會在這上面提供!

好了,今天的分享就到這裡了,後面棧長會分享更多好玩的 Java 技術和最新的技術資訊,關註公眾號Java技術棧第一時間推送,我也將主流 Java 面試題和參考答案都整理好了,在公眾號後臺回覆關鍵字 "面試" 進行刷題。

最後,覺得我的文章對你用收穫的話,動動小手,給個在看、轉發,原創不易,棧長需要你的鼓勵。

版權聲明: 本文系公眾號 "Java技術棧" 原創,轉載、引用本文內容請註明出處,抄襲、洗稿一律投訴侵權,後果自負,並保留追究其法律責任的權利。

近期熱文推薦:

1.1,000+ 道 Java面試題及答案整理(2022最新版)

2.勁爆!Java 協程要來了。。。

3.Spring Boot 2.x 教程,太全了!

4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!

5.《Java開發手冊(嵩山版)》最新發佈,速速下載!

覺得不錯,別忘了隨手點贊+轉發哦!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文代碼: https://gitee.com/felord/spring-security-oauth2-tutorial/tree/wwopen/ 現在很多企業都接入了企業微信,作為私域社群工具,企業微信開放了很多API,可以打通很多自有的應用。既然是應用,那肯定需要做登錄。正好企業微信提供了企 ...
  • 變數(variable)可以理解成一塊記憶體區域,通過變數名,可以引用這塊記憶體區域,獲取裡面存儲的值。 變數名 標識符(identifier)命名有嚴格的規範。 只能由字母、數字和下劃線(_)組成。 不能以數字開頭。 長度不能超過63個字元。 不能使用關鍵字和保留字。 auto, break, cas ...
  • 1、從規範角度分析,一般是禁止使用C++的異常機制的。 2、要求所有的錯誤都應該通過錯誤值在函數間傳遞病做相應的判斷,而不應該通過異常機制進行錯誤處理。 3、編碼人員必須完全掌控自己的整個編碼過程,要有攻擊者思維,主動把握有可能出錯的環節,儘可能的分析出程式的所有異常,增強安全編碼意識。 4、使用c ...
  • ​ 1,建一個表 create table 表名( 屬性a 類型 限制, 屬性b 類型 限制 ) ​編輯 2,向表裡添加數據 insert into Tset(屬性a,屬性b) values(a的數據,b的數據) 給屬性a,屬性b添加數據 insert into Tset values(a的數據,b ...
  • 排序演算法總結 1.十大經典演算法及性能 2.具體排序演算法 1.冒泡排序 迴圈過程中比較相鄰兩個數大小,通過交換正確排位,迴圈整個數組即可完成排序 圖片演示 代碼實現Java //冒泡排序 public static Integer[] Bubble(Integer[] array){ boolean ...
  • 前言 不知道有沒有小伙伴跟我一樣,每次刷抖音都不想動手,好希望能夠有什麼東西代替我的手指,我給它一個命令,它就明白我要什麼。於 是,我利用空閑時間操作了一下,終於用Python把自動刷抖音給搞出來了,這下真的是解決了我長久以來的困擾… 工具準備 1.Python3.7.7 2.adb(Android ...
  • 我們知道 Python 有很多運算符可以進行數學運算,如果是簡單的問題還好說,但是要處理一些相對複雜的問題也要我們自己一行一行手動的來編寫嗎?答案當然不是,Python 提供了 math 模塊對一些數學運算提供了支持。 1.簡介 math 模塊提供了對 C 標准定義的數學函數的訪問,但該模塊並不支持 ...
  • Skywalking介紹 Skywalking是一個國產的開源框架,2015年有吳晟個人開源,2017年加入Apache孵化器,國人開源的產品,主要開發人員來自於華為,2019年4月17日Apache董事會批准SkyWalking成為頂級項目,支持Java、.Net、NodeJs等探針,數據存儲支持 ...
一周排行
    -Advertisement-
    Play Games
  • GoF之工廠模式 @目錄GoF之工廠模式每博一文案1. 簡單說明“23種設計模式”1.2 介紹工廠模式的三種形態1.3 簡單工廠模式(靜態工廠模式)1.3.1 簡單工廠模式的優缺點:1.4 工廠方法模式1.4.1 工廠方法模式的優缺點:1.5 抽象工廠模式1.6 抽象工廠模式的優缺點:2. 總結:3 ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 本章將和大家分享ES的數據同步方案和ES集群相關知識。廢話不多說,下麵我們直接進入主題。 一、ES數據同步 1、數據同步問題 Elasticsearch中的酒店數據來自於mysql資料庫,因此mysql數據發生改變時,Elasticsearch也必須跟著改變,這個就是Elasticsearch與my ...
  • 引言 在我們之前的文章中介紹過使用Bogus生成模擬測試數據,今天來講解一下功能更加強大自動生成測試數據的工具的庫"AutoFixture"。 什麼是AutoFixture? AutoFixture 是一個針對 .NET 的開源庫,旨在最大程度地減少單元測試中的“安排(Arrange)”階段,以提高 ...
  • 經過前面幾個部分學習,相信學過的同學已經能夠掌握 .NET Emit 這種中間語言,並能使得它來編寫一些應用,以提高程式的性能。隨著 IL 指令篇的結束,本系列也已經接近尾聲,在這接近結束的最後,會提供幾個可供直接使用的示例,以供大伙分析或使用在項目中。 ...
  • 當從不同來源導入Excel數據時,可能存在重覆的記錄。為了確保數據的準確性,通常需要刪除這些重覆的行。手動查找並刪除可能會非常耗費時間,而通過編程腳本則可以實現在短時間內處理大量數據。本文將提供一個使用C# 快速查找並刪除Excel重覆項的免費解決方案。 以下是實現步驟: 1. 首先安裝免費.NET ...
  • C++ 異常處理 C++ 異常處理機制允許程式在運行時處理錯誤或意外情況。它提供了捕獲和處理錯誤的一種結構化方式,使程式更加健壯和可靠。 異常處理的基本概念: 異常: 程式在運行時發生的錯誤或意外情況。 拋出異常: 使用 throw 關鍵字將異常傳遞給調用堆棧。 捕獲異常: 使用 try-catch ...
  • 優秀且經驗豐富的Java開發人員的特征之一是對API的廣泛瞭解,包括JDK和第三方庫。 我花了很多時間來學習API,尤其是在閱讀了Effective Java 3rd Edition之後 ,Joshua Bloch建議在Java 3rd Edition中使用現有的API進行開發,而不是為常見的東西編 ...
  • 框架 · 使用laravel框架,原因:tp的框架路由和orm沒有laravel好用 · 使用強制路由,方便介面多時,分多版本,分文件夾等操作 介面 · 介面開發註意欄位類型,欄位是int,查詢成功失敗都要返回int(對接java等強類型語言方便) · 查詢介面用GET、其他用POST 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...