主頁 > 軟體設計 > 為什么我們可以呼叫來自Java中另一個執行緒的物件的方法?

為什么我們可以呼叫來自Java中另一個執行緒的物件的方法?

2021-11-12 18:06:01 軟體設計

我正在閱讀一個簡單的 Java 多執行緒聊天室。在程式中,有一個名為 的類Chatroom,它有方法broadcast該方法被另一個serverThread執行緒呼叫,并在原始執行緒(聊天室執行緒)中列印了一些訊息。

我對此完全困惑。我的問題是:

  1. 怎么可能就這樣從另一個執行緒呼叫一個方法?我們不是必須做某種“信號”或將某些東西放入共享資料空間,以便另一個執行緒中的方法可以自發地采取相應的行動嗎?
  2. 即使有可能。為什么它不在呼叫者執行緒中輸出,而是在定義它的執行緒中輸出?
  3. 我猜一個更普遍的問題是:在多執行緒的情況下如何翻譯和執行代碼?OOP 只是讓我感到更加困惑。(如果你能指出我更多的資源來查看,我將非常感激)

Java代碼

public class ChatRoom {

    private ArrayBlockingQueue<ServerThread> serverThreads; // List<ChatRoom.ServerThread>

    // Entrance of the place
    public static void main(String [] args)
    {
        new ChatRoom(6789);
    }

    public ChatRoom(int port)
    {
        try
        {
            System.out.println("Binding to port "   port);
            ServerSocket ss = new ServerSocket(port);
            serverThreads = new ArrayBlockingQueue<ServerThread>(5); // new ArrayList<>();
            while(true)
            {
                Socket s = ss.accept();   //  Accept the incoming request
                System.out.println("Connection from "   s   " at "   new Date());
                ServerThread st = new ServerThread(s, this); //connection handler
                System.out.println("Adding this client to active client list");
                serverThreads.add(st);
            }
        }
        catch (Exception ex) {
            System.out.println("Server shut down unexpectedly.");
            return;
        }

    }

    public void broadcast(String message)
    {
        if (message != null) {
            System.out.println("broadcasting ..."   message);
            for(ServerThread threads : serverThreads)
                    threads.sendMessage(message);
        }
    }

}


public class ServerThread extends Thread {

    private PrintWriter pw;
    private BufferedReader br;
    private ChatRoom cr;
    private Socket s;

    public ServerThread(Socket s, ChatRoom cr)
    {
        this.s = s;
        this.cr = cr;
        try
        {
            pw = new PrintWriter(s.getOutputStream(), true);
            br = new BufferedReader(new InputStreamReader(s.getInputStream()));
            start();
        }
        catch (IOException ex) {ex.printStackTrace();}
    }

    public void sendMessage(String message)
    {
        pw.println(message);
    }

    public void run()
    {
        try {
            while(true)
            {
                String line = br.readLine();
                //if(line == null) break; // client quits
                cr.broadcast(line);   // Send text back to the clients
            }
        }
        catch (Exception ex) {ex.printStackTrace();}
        finally {
            try {
                pw.close();
                br.close();
                s.close();
            }
            catch (Exception ex) {ex.printStackTrace();}
        }//finally
    }//run
}

這是輸出。在我看來,“廣播訊息”不是在ServerThread執行緒中列印的(順便說一句,我不知道如何顯示其輸出),而是在Chatroom執行緒中列印

輸出

uj5u.com熱心網友回復:

所有執行緒都列印到只有一個標準輸出嗎?

System是類的名稱,并且System.out該類static成員的名稱在任何給定的時間點只能有一個System.out物件——一個PrintStream物件。

通常,Java 運行時環境設定System.out為指向一些有用的地方,例如控制臺視窗。System.out不是final,因此您的程式(或您的程式* 呼叫的某個庫)可能會重新分配它以將輸出發送到其他地方。

在執行緒中呼叫物件的方法時,是否所有代碼都像在該執行緒“內部”一樣執行?

是的。這就是執行緒所做的。他們執行你的代碼。每個執行緒開始在run()某個Runnable實體方法中執行您的代碼,并且從那時起繼續執行您的代碼告訴它執行的任何操作,直到 (a) 到達run()方法的末尾,或 (b) 拋出例外那沒有被抓住。

不過,我不會說“內部”。執行緒不是容器。執行緒“內部”沒有任何東西,盡管通常有一些其他執行緒不訪問或無法訪問的變數(例如,執行緒呼叫的所有函式的所有區域變數)。


*圖書館可能這樣做,但圖書館這樣做將是一件非常粗魯的事情,除非檔案非常清楚會發生什么。

uj5u.com熱心網友回復:

該方法由另一個 serverThread 執行緒呼叫,并原始執行緒(聊天室執行緒)中列印一些訊息

這是一個有點誤導性的陳述,具體取決于您對“in”一詞的含義。每個ServerThread物件都傳遞了ChatRoom物件并回呼到該ChatRoom.broadcast(...)方法。不要因為它們是執行緒而感到困惑。這只是一個物件呼叫另一個物件的方法。

為什么它不在呼叫者執行緒中輸出,而是在定義它的執行緒中輸出?

因為是呼叫者執行緒在進行呼叫。僅僅因為您在執行緒方法之間來回呼叫并不意味著不同的執行緒在進行呼叫。該練習試圖令人困惑。同樣,這些只是呼叫其他物件的物件,這里沒有魔術執行緒信號。

在多執行緒的情況下如何翻譯和執行代碼?

無論您是否有多個執行緒,代碼在 Java OOP 中的作業方式都是相同的。如果 ThreadA 正在運行并呼叫,chatRoom.broadcast("foo")則是 ThreadA 執行該方法。如果該方法轉向并對每個方法進行大量呼叫,serverThread.sendMessage(foo)那么它仍然是 ThreadA 正在運行并進行這些方法呼叫。您實際上必須做很多作業才能在執行緒之間傳遞控制權。

怎么可能就這樣從另一個執行緒呼叫一個方法?我們不是必須做某種“信號”或將某些東西放入共享資料空間,以便另一個執行緒中的方法可以自發地采取相應的行動嗎?

僅僅因為一個執行緒呼叫另一個執行緒的方法并不意味著存在任何信令或自動資料共享。這在很大程度上取決于正在訪問的資料。

讓我們看看呼叫的每個部分。ThreadA 回呼到chatroom.broadCast(...). 在該方法中message是確定的,因為它是在傳遞給訪問System.out.println(...)synchronized PrintStream這也是確定,所以它可以被使用,并且ArrayBlockingQueuesynchronized使作品。沒有未受保護的欄位無法Chatroom訪問。然后,您必須評估ServerThread.sendMessage(...)使用PrintWriter具有內部鎖的a 的回呼所以這是猶太潔食。同樣,如果對每個ServerThread物件的本地欄位有一些訪問,則需要以某種方式鎖定它。

OOP 只是讓我感到更加困惑。

我認為這是一個旨在在這種情況下令人困惑問題,我認為這是一個學術練習。至于你如何弄清楚它在做什么,我會列印出來,Thread.currentThread().getId()這樣你就可以看到哪個執行緒正在列印什么。我還會減少執行緒數,然后將其放大,直到您可以遵循它。

逐行執行并記住執行緒不會將控制權移交給其他執行緒,而無需您會看到的特定呼叫。

警告:練習中有幾個錯誤需要修復。希望下面的內容不會讓您感到困惑,因為這有點像是校隊的話題。

  1. 中的所有欄位ServerThread都應標記為finalfinal強制在ServerThread建構式完成之前完全初始化欄位這非常重要,否則新的ServerThread可能會在正確設定之前訪問它自己的欄位。是的,這是瘋狂的東西,但這是語言定義的一部分。對于這個問題,這將是有一個良好的模式Chatroom.serverThreads也可以finalfinal如果可能的話,應該在建構式中初始化任何東西
  2. 作為規則和上一點的延續,你永遠不start()應該在它自己的建構式中使用執行緒您冒著讓執行緒在初始化之前訪問它自己的欄位或讓其他執行緒訪問未初始化的欄位的風險。構造物件然后呼叫start()它是正確的做法。
  3. Chatroom物件在其建構式中也做得太多了。它不應該在其建構式中創建其他執行緒,然后回呼Chatroom可能未初始化的 。構造套接字并且serverThreads應該在建構式中,但是while在建構式完成后,應該在另一個方法中完成創建新服務器執行緒回圈。

希望這可以幫助。

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/356493.html

標籤:爪哇 多线程 哎呀

上一篇:我可以在不使用__constructor的情況下完成這項作業嗎

下一篇:嘗試在新類中使用另一個類的方法時,我不斷收到位置引數錯誤

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more