初學Java多線程:向線程傳遞數據的三種方法

2020-12-13 51CTO

初學Java多線程:向線程傳遞數據的三種方法

本文講述在學習Java多線程中需要學習的向線程傳遞數據的三種方法。由於線程的運行和結束是不可預料的,因此,在傳遞和返回數據時就無法象函數一樣通過函數參數和return語句來返回數據。

作者:nokiaguy來源:真的有外星人嗎|2009-06-29 18:18

在傳統的同步開發模式下,當我們調用一個函數時,通過這個函數的參數將數據傳入,並通過這個函數的返回值來返回最終的計算結果。但在多線程的異步開發模式下,數據的傳遞和返回和同步開發模式有很大的區別。由於線程的運行和結束是不可預料的,因此,在傳遞和返回數據時就無法象函數一樣通過函數參數和return語句來返回數據。本文就以上原因介紹了幾種用於向線程傳遞數據的方法,在下一篇文章中將介紹從線程中返回數據的方法。

欲先取之,必先予之。一般在使用線程時都需要有一些初始化數據,然後線程利用這些數據進行加工處理,並返回結果。在這個過程中***要做的就是向線程中傳遞數據。

一、通過構造方法傳遞數據

在創建線程時,必須要建立一個Thread類的或其子類的實例。因此,我們不難想到在調用start方法之前通過線程類的構造方法將數據傳入線程。並將傳入的數據使用類變量保存起來,以便線程使用(其實就是在run方法中使用)。下面的代碼演示了如何通過構造方法來傳遞數據:

  1. package mythread;  
  2.  
  3. public class MyThread1 extends Thread  
  4. {  
  5.     private String name;  
  6.  
  7.     public MyThread1(String name)  
  8.     {  
  9.         this.name = name;  
  10.     }  
  11.     public void run()  
  12.     {  
  13.         System.out.println("hello " + name);  
  14.     }  
  15.     public static void main(String[] args)  
  16.     {  
  17.         Thread thread = new MyThread1("world");  
  18.         thread.start();          
  19.     }  
  20. }  

由於這種方法是在創建線程對象的同時傳遞數據的,因此,在線程運行之前這些數據就就已經到位了,這樣就不會造成數據在線程運行後才傳入的現象。如果要傳遞更複雜的數據,可以使用集合、類等數據結構。使用構造方法來傳遞數據雖然比較安全,但如果要傳遞的數據比較多時,就會造成很多不便。由於Java沒有默認參數,要想實現類似默認參數的效果,就得使用重載,這樣不但使構造方法本身過於複雜,又會使構造方法在數量上大增。因此,要想避免這種情況,就得通過類方法或類變量來傳遞數據。

二、通過變量和方法傳遞數據

向對象中傳入數據一般有兩次機會,***次機會是在建立對象時通過構造方法將數據傳入,另外一次機會就是在類中定義一系列的public的方法或變量(也可稱之為欄位)。然後在建立完對象後,通過對象實例逐個賦值。下面的代碼是對MyThread1類的改版,使用了一個setName方法來設置name變量:

  1. package mythread;  
  2.  
  3. public class MyThread2 implements Runnable  
  4. {  
  5.     private String name;  
  6.  
  7.     public void setName(String name)  
  8.     {  
  9.         this.name = name;  
  10.     }  
  11.     public void run()  
  12.     {  
  13.         System.out.println("hello " + name);  
  14.     }  
  15.     public static void main(String[] args)  
  16.     {  
  17.         MyThread2 myThread = new MyThread2();  
  18.         myThread.setName("world");  
  19.         Thread thread = new Thread(myThread);  
  20.         thread.start();  
  21.     }  
  22. }  

三、通過回調函數傳遞數據

上面討論的兩種向線程中傳遞數據的方法是最常用的。但這兩種方法都是main方法中主動將數據傳入線程類的。這對於線程來說,是被動接收這些數據的。然而,在有些應用中需要在線程運行的過程中動態地獲取數據,如在下面代碼的run方法中產生了3個隨機數,然後通過Work類的process方法求這三個隨機數的和,並通過Data類的value將結果返回。從這個例子可以看出,在返回value之前,必須要得到三個隨機數。也就是說,這個value是無法事先就傳入線程類的。

  1. package mythread;  
  2.  
  3. class Data  
  4. {  
  5.     public int value = 0;  
  6. }  
  7. class Work  
  8. {  
  9.     public void process(Data data, Integer numbers)  
  10.     {  
  11.         for (int n : numbers)  
  12.         {  
  13.             data.value += n;  
  14.         }  
  15.     }  
  16. }  
  17. public class MyThread3 extends Thread  
  18. {  
  19.     private Work work;  
  20.  
  21.     public MyThread3(Work work)  
  22.     {  
  23.         this.work = work;  
  24.     }  
  25.     public void run()  
  26.     {  
  27.         java.util.Random random = new java.util.Random();  
  28.         Data data = new Data();  
  29.         int n1 = random.nextInt(1000);  
  30.         int n2 = random.nextInt(2000);  
  31.         int n3 = random.nextInt(3000);  
  32.         work.process(data, n1, n2, n3);    
  33.         System.out.println(String.valueOf(n1) + "+" + String.valueOf(n2) + "+" 
  34.                 + String.valueOf(n3) + "=" + data.value);  
  35.     }  
  36.     public static void main(String[] args)  
  37.     {  
  38.         Thread thread = new MyThread3(new Work());  
  39.         thread.start();  
  40.     }  
  41. }  

在上面代碼中的process方法被稱為回調函數。從本質上說,回調函數就是事件函數。在Windows API中常使用回調函數和調用API的程序之間進行數據交互。因此,調用回調函數的過程就是最原始的引發事件的過程。在這個例子中調用了process方法來獲得數據也就相當於在run方法中引發了一個事件。

【編輯推薦】

  1. 初學Java多線程:慎重使用volatile關鍵字
  2. 初學Java多線程:join方法的使用
  3. 初學Java多線程:線程的生命周期
  4. 初學Java多線程:使用Runnable接口創建線程
  5. 初學Java多線程:用Thread類創建線程

【責任編輯:

楊賽

TEL:(010)68476606】

點讚 0

相關焦點

  • 大數據基礎:Java多線程入門
    在大數據開發學習當中,Java基礎是非常重要的一部分,打好了Java基礎,才能在後續的大數據框架技術學習階段,也能有所主力。而Java當中的一個重要知識點,就是多線程。今天的大數據基礎分享,我們就主要來講講Java多線程入門基礎。
  • JAVA多線程 集合同步
    經典做法在迭代開始之前,使用synchronized手動同步所有針對List的修改操作(增加、刪除),保證迭代期間沒有線程修改List。此方法需要明確各個方法的同步,考慮的因素很多,不建議使用。B.Vector 和Hashtable 在Java歷史早期就已經存在的,一開始它們就被設計為線程安全的,查看它們的源碼時你會發現其方法都是同步方法。然而它們很快就暴露出多線程下性能非常糟糕的表現。眾所周知,同步(synchronization)需要取得耗費時間監視的同步鎖(locks),因而降低性能。
  • Java多線程synchronized
    本篇主要介紹Java多線程中的同步,也就是如何在Java語言中寫出線程安全的程序,如何在Java語言中解決非線程安全的相關問題。
  • Java編寫線程安全類的7個技巧
    一、無狀態(No State)當多個線程訪問相同的實例或靜態變量時,必須以某種方式來協調對此變量的訪問。最簡單的方法就是避免使用實例或靜態變量。對於沒有實例變量的類,它的方法只使用局部變量和方法參數。在以下示例中,pool和workQueue對於單個工作線程是本地的。另一種實現線程局部變量的方法是使用java.lang.ThreadLocal類來作為你想創建「本地線程」的欄位。這是一個使用java.lang.ThreadLocal的實例變量的例子:在java.lang.ThreadLocal中封裝實例變量的類型。
  • Java多線程編程必備基礎知識
    進程 VS 線程進程和線程是包含關係,但是多任務既可以由多進程實現,也可以由線程實現,還可以混合多進程+多線程。自定義線程的實現處於實用的角度出發,想要使用多線程,那麼第一步就是需要知道如何實現自定義線程,因為實際開發中,需要線程完成的任務是不同的,所以我們需要根據線程任務來自定義線程,JDK 為我們的開發人員提供了三種自定義線程的方式,供實際開發中使用,來開發出符合需求的多線程程序!
  • 面試前必看Java線程面試題
    - 封裝:通常認為封裝是把數據和操作數據的方法綁定起來,對數據的訪問只能通過已定義的接口。面向對象的本質就是將現實世界描繪成一系列完全自治、封閉的對象。我們在類中編寫的方法就是對實現細節的一種封裝;我們編寫一個類就是對數據和數據操作的封裝。
  • Java多線程帶返回值得Callable接口
    Java多線程帶返回值的Callable接口在面試的時候,有時候是不是會遇到面試會問你,Java中實現多線程的方式有幾種?你知道嗎?你知道Java中有可以返回值的線程嗎?在具體的用法你知道嗎?如果兩個線程同時來調用同一個計算對象,計算對象的call方法會被調用幾次你知道嗎?
  • 高級分享:Java多線程你真的理解透徹了嗎?帶你玩轉一次多線程!
    不知道怎麼引入正文相信後端同學在開發的時候多多少少都會涉及到多線程開發,作為Java開發的我也同樣會經常用到多線程開發。我認為Java語言在處理多線程上是非常優秀的,我們可以使用簡明的代碼實現線程的創建、啟動、管理等。
  • 實現多線程的標準操作,基於Runnable接口實現java多線程
    1 為什麼要用Runnable上一篇文章介紹了通過繼承Thread類,實現java多線程。但如果當我們創建的這個線程類還想繼承其他類的時候,這種方法就略顯局限了。這也是java單繼承的局限性。為了避免這種局限性,所以又提供了第二種多線程主體定義的形式:實現Runnable接口。
  • Java面試題-多線程篇十三
    線程是作業系統能夠進行運算調度的最小單位,它被包含在進程之中,是進程中的實際運作單位。程式設計師可以通過它進行多處理器編程,你可以使用多線程對運算密集型任務提速。比如,如果一個線程完成一個任務要100毫秒,那麼用十個線程完成改任務只需10毫秒。122,線程和進程有什麼區別?
  • Java 線程安全問題的本質
    所以理解上述兩個問題的核心,對認知多線程的問題則具有很高的意義;簡單理解CPUCPU除了控制器、運算器等器件還有一個重要的部件就是寄存器。其中寄存器的作用就是進行數據的臨時存儲。一般重排序可以分為如下三種:
  • java線程的基礎問題講解
    所以上下文切換會影響線程的執行速度。join 的作用多線程一定比單線程快嗎?不一定,在測試中並發數量沒超過百萬次的時候,串行比並發速度更快,因為線程有線程的創建和上下文切換的開銷。方法有無鎖並發編程、CAS算法、使用最少線程和使用協程無鎖並發編程:多線程競爭鎖時,會引起上下文切換,所以多線程處理數據的時候,可以用一些方法避免使用鎖,如將數據的ID安裝hash算法取模分段,不同線程處理不同段的數據
  • Java基礎知識點面試手冊(線程+JDK8)
    高並發編程多線程和單線程的區別和聯繫:答:在單核 CPU 中,將 CPU 分為很小的時間片,在每一時刻只能有一個線程在執行,是一種微觀上輪流佔用 CPU 的機制。多線程會存在線程上下文切換,會導致程序執行速度變慢,即採用一個擁有兩個線程的進程執行所需要的時間比一個線程的進程執行兩次所需要的時間要多一些。
  • 40個Java多線程問題總結
    試想,如果單核CPU使用單線程,那麼只要這個線程阻塞了,比方說遠程讀取某個數據吧,對端遲遲未返回又沒有設置超時時間,那麼你的整個程序在數據返回回來之前就停止運行了。多線程可以防止這個問題,多條線程同時運行,哪怕一條線程的代碼執行讀取數據阻塞,也不會影響其它任務的執行。(3)便於建模這是另外一個沒有這麼明顯的優點了。
  • Java 線程面試題 Top 50
    若你實在找不到答案,可以在文章的評論中向我求助。你也可以在這找到一些答案Java線程問答Top 12。50道Java線程面試題下面是Java線程相關的熱門面試題,你可以用它來好好準備面試。1) 什麼是線程?
  • java多線程之Thread構造函數(源碼分析)
    在上一篇文章中對線程狀態生命周期和常見的線程api進行了一個講解。這篇文章開始著重對其構造方法進行一個說明,也將揭曉為什麼我們調用了start方法就能啟動一個線程。一、守護線程和非守護線程我們獲取線程的id的時候會發現每次都不是0,這是因為在java虛擬機運行一個線程的時候會默認啟動一些其他的線程,來為我們的線程服務。
  • java的線程創建方式
    Thread類java語言中的Thread類是一個基本的線程類,用於創建線程、中斷線程、獲取線程的基本信息、運行狀態等。我們首先了解下利用Thread類創建線程實例的二種方式。繼承Thread類創建線程//繼承Thread實現自己的線程類class MyThread extends Thread{//重寫run方法,給線程賦予工作任務 @Override public void run() { //任務內容…… System.out.println("當前線程是:"+Thread.currentThread
  • Java 多線程 —— 深入理解 volatile 的原理以及應用
    推薦閱讀:《java 多線程—線程怎麼來的》這一篇主要講解一下volatile的原理以及應用,想必看完這一篇之後,你會對volatile的應用原理以及使用邊界會有更深刻的認知。happens-before是java內存模型向我們提供的內存可見性保證,這也就是我們第一個問題的解答,volatiel如何保證對共享變量同步的。
  • 最全面的Java多線程用法解析
    最全面的java多線程用法解析,如果你對Java的多線程機制並沒有深入的研究,那麼本文可以幫助你更透徹地理解Java多線程的原理以及使用方法。1.創建線程在Java中創建線程有兩種方法:使用Thread類和使用Runnable接口。在使用Runnable接口時需要建立一個Thread實例。
  • Java面試題解析(事務+緩存+資料庫+多線程+JVM)
    阻塞的情況分三種:等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待池中。(wait會釋放持有的鎖)同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM會把該線程放入鎖池中。