當前位置:首頁 » 編程語言 » java線程的通訊

java線程的通訊

發布時間: 2023-01-12 22:57:11

java線程之間如何通信

  • volatile修飾的變數具有可見性。可見性也就是說一旦某個線程修改了該被volatile修飾的變數,它會保證修改的值會立即被更新到主存,當有其他線程需要讀取時,可以立即獲取修改之後的值。在Java中為了加快程序的運行效率,對一些變數的操作通常是在該線程的寄存器或是CPU緩存上進行的,之後才會同步到主存中,而加了volatile修飾符的變數則是直接讀寫主存。

  • volatile禁止指令重排 ,指令重排是指處理器為了提高程序運行效率,可能會對輸入代碼進行優化,它不保證各個語句的執行順序同代碼中的順序一致,但是它會保證程序最終執行結果和代碼順序執行的結果是一致的。指令重排序不會影響單個線程的執行,但是會影響到線程並發執行的正確性。程序執行到volatile修飾變數的讀操作或者寫操作時,在其前面的操作肯定已經完成,且結果已經對後面的操作可見,在其後面的操作肯定還沒有進行。

  • synchronized可作用於一段代碼或方法,既可以保證可見性,又能夠保證原子性。可見性體現在:通過synchronized或者Lock能保證同一時刻只有一個線程獲取鎖然後執行同步代碼,並且在釋放鎖之前會將對變數的修改刷新到主存中。
    原子性表現在:要麼不執行,要麼執行到底。

  • 總結

  • 從而我們可以看出volatile雖然具有可見性但是並不能保證原子性。

  • 性能方面,synchronized關鍵字是防止多個線程同時執行一段代碼,就會影響程序執行效率,而volatile關鍵字在某些情況下性能要優於synchronized。

  • 但是要注意volatile關鍵字是無法替代synchronized關鍵字的,因為volatile關鍵字無法保證操作的原子性。

⑵ 如何在學習Java過程中實現線程之間的通信

在java中,每個對象都有兩個池,鎖池(monitor)和等待池(waitset),每個對象又都有wait、notify、notifyAll方法,使用它們可以實現線程之間的通信,只是平時用的較少.

wait(): 使當前線程處於等待狀態,直到另外的線程調用notify或notifyAll將它喚醒

notify(): 喚醒該對象監聽的其中一個線程(規則取決於JVM廠商,FILO,FIFO,隨機…)

notifyAll(): 喚醒該對象監聽的所有線程

鎖池: 假設T1線程已經擁有了某個對象(注意:不是類)的鎖,而其它的線程想要調用該對象的synchronized方法(或者synchronized塊),由於這些線程在進入對象的synchronized方法之前都需要先獲得該對象的鎖的擁有權,但是該對象的鎖目前正被T1線程擁有,所以這些線程就進入了該對象的鎖池中.

等待池: 假設T1線程調用了某個對象的wait()方法,T1線程就會釋放該對象的鎖(因為wait()方法必須出現在synchronized中,這樣自然在執行wait()方法之前T1線程就已經擁有了該對象的鎖),同時T1線程進入到了該對象的等待池中.如果有其它線程調用了相同對象的notifyAll()方法,那麼處於該對象的等待池中的線程就會全部進入該對象的鎖池中,從新爭奪鎖的擁有權.如果另外的一個線程調用了相同對象的notify()方法,那麼僅僅有一個處於該對象的等待池中的線程(隨機)會進入該對象的鎖池.

java實現線程間通信的四種方式

1、synchronized同步:這種方式,本質上就是「共享內存」式的通信。多個線程需要訪問同一個共享變數,誰拿到了鎖(獲得了訪問許可權),誰就可以執行。

2、while輪詢:其實就是多線程同時執行,會犧牲部分CPU性能。

3、wait/notify機制

4、管道通信:管道流主要用來實現兩個線程之間的二進制數據的傳播

⑶ java線程間通信問題

import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;

public class ThreadDemo {

/**
* Semaphore 就是大學操作系統裡面講的信號量, 其方法acquire和release分別對應PV操作
* AtomicInteger 是原子變數,對它的操作會轉化為底層的原語(不可分割的操作),這樣多線程並發對其操作就不會有問題,
* 如果是普通的int就還要加鎖才能保證沒問題
*/
public static void main(String[] args) throws InterruptedException {
// 用於啟動另一個線程
Semaphore startThread = new Semaphore(1);
// 用於控制終止程序
AtomicInteger threadCount = new AtomicInteger(0);

for (int i = 1; i <= 10; i++) {
CountThread t = new CountThread("Thread" + i, startThread,
threadCount);
t.start();
}
}
}

class CountThread extends Thread {
// 線程標識
private String label;
// 用於啟動另一個線程
private Semaphore startThread;
// 用於控制終止程序
private AtomicInteger threadCount;

public CountThread(String label, Semaphore startThread,
AtomicInteger threadCount) {
this.label = label;
this.startThread = startThread;
this.threadCount = threadCount;
}

public void run() {
try {
// 等待線程被喚醒
startThread.acquire();

System.out.println("------線程:" + label + " 開始工作------");
} catch (InterruptedException e) {
e.printStackTrace();
}

int num = 0;
while (true) {
System.out.println("線程:" + label + "計數:" + num);
// 計數到5
if (num++ == 5) {
// 喚醒另一個計數線程
startThread.release();
// 10的時候程序終止, incrementAndGet是遞增(也就是++操作), 再取值
if (threadCount.incrementAndGet() == 10) {
System.exit(1);
}
}
}
}
}

研究Java並發,強烈推薦你看《Java並發編程實踐》

⑷ Java 中利用管道實現線程間的通訊

在Java 語言中 提供了各種各樣的輸入輸出流(stream) 使我們能夠很方便的對數據進行操作 其中 管道(pipe)流是一種特殊的流 用於在不同線程(threads)間直接傳送數據 一個線程發送數據到輸出管道 另一個線程從輸入管道中讀數據 通過使用管道 實現不同線程間的通訊 無需求助於類似臨時文件之類的東西 本文在簡要介紹管道的基本概念後 將以一個具體的實例pipeapp加以詳細說明 .管道的創建與使用Java提供了兩個特殊的專門的類專門用於處理管道 它們就是pipedinputstream類和pipeoutputstream類 Pipedinputstream代表了數據在管道中的輸出端 也就是線程向管道讀數據的一端 pipeoutputstream代表了數據在管道中的輸入端 也就是線程向管道寫數據的一端 這兩個類一起使用可以提供數據的管道流 為了創建一個管道流 我們必須首先創建一個pipeoutstream對象 然後 創建pipeinputstream對象 實例如下 pipeout= new pipedyoutstream();pipein= new pipedputsteam(pipepout);一旦創建了一個管道後 就可以象操作文件一樣對管道進行數據的讀寫 .演示程序 pipeapp應用程序由三個程序組成 主線程(pipeapp Java)及由主線程啟動的兩個二級線程(ythread Java和zthread Java) 它們使用管道來處理數據 程序從一個內容為一行一行 x 字母的 input txt 文件中讀取數據 使用管道傳輸數據 第一次是利用線程ythread將數據 x 轉換為 y 最後利用線程zthread將 y 轉換為 z 之後 程序在屏幕上顯示修改後的數據 主線程 (pipeapp Java)在main()方法中 程序首先創建一個應用對象 pipeapp pipeapp=new pipeapp();由於程序中流操作都需要使用IOException異常處理 所以設置了一個try塊 在try中 為了從源文件中讀取數據 程序為 input txt 文件創建了一個輸入流Xfileln :fileinputstream xfileln= new fileinputstream( input txt );新的輸入流傳遞給changetoy()方法 讓線程ythread能讀取該文件 inputstream ylnpipe =pipeapp changetoy(xfileln);changetoy()方法創建將輸入數據 x 改變到 y 的線程ythread 並返回該線程的輸入管道 inputstream zlnpipe = pipeapp changetoz(ylnpipe);changetoz()方法啟動將數據從 y 改變到 z 的線程zehread 主程序將使用從changetoz()返回的輸入管道 得到以修改的數據 然後 程序將管道輸入流定位到datainputstream對象 使程序能夠使用readline()方法讀取數據 datainputstream inputstream = new datainputstream(zlnpiepe);創建了輸入流以後 程序就可以以行一行的讀取數據病顯示在屏幕上 String str= inputstream readline();While(str!=null){system out println(str);str=inputstream readline();} 顯示完成之後 程序關閉輸入流 inputstream close();changetoy()方法 changetoy()方法首先通過傳遞一個參數inputstream給datainputstream對象來定位資源的輸入流 使程序能使用readline()方法從流中讀取數據 datainputstream xfileln =new datainutstream(inputstream) 然後 changetoy()創建輸出管道和輸入管道 pipeoutstream pipeout = new pipeoutputstream();pipeinputstream pipeln = new pipedinputsteam(pipeout); 為了能夠使用println()方法輸出修改的後的文本行到管道 程序將輸出管道定位到printstream對象 printstream printstream = new printstream(pipeout);現在 程序可以創建將數據從x改變到y的線程 該線程是ythread類的一個對象 他傳遞兩個參數 輸入文件(xfileln)和輸出管道(調用printstream)ythread ythread =new thread(xfileln printstream);之後 程序啟動線程 changetoz()方法changetoz()方法與changetoy()方法很相似 他從changetoy()返回的輸入流開始 datainputstream yfileln= new datainputstream(inputstream);程序創建一個新的管道 pipedoutstream pipeout = new pipedoutputstream();pipedinputstream pipeln = new pipedinputsream(pipeout ); 該線程通過這個新的管道發出修改後的數據(輸入流pipeln )給主程序 源程序如下 ////pipeapp Java pipeapp的主應用程序//import Java io *class pipeapp{public static void main(string[] args){pipeapp pipeapp=new pipeapp();try{fileinputstream xfile =new fileinputstream( input txt );inputstream ylnpipe = pipeapp changetoy(xfileln);inputstream zlnpipe=pipeapp changetoz(ylnpipe);system out println();system out println( here are the results );system out pringln();datainputstream inputstream = nes datainputstream(zlnpipe);string str = inputstream readline();while (str!=null){system out println(str);str=inputstream readline();}inputstream close();}catch(exception e){system out println(e tostring());}}public inputstream changetoy(inputstream inputstream){try{datainputstream pipeout = new datainputsteam(inputstream);pipedoutstream pipeout = new pipedoutputstream();pipedlnsteam pipeln = new pipedlnputstream(pipeout);printstream printstream = new printstream(pipeout);ythread ythread = new ythread(xfileln printstream);ythread start();return pipeln;}catch(exeption e){system out println(x tostring());}return null;}public inputstream changetoz(inputstream inputsteam){try{datainputstream yfileln = new datainputstream(inputstream);pipeoutputstream pipeln = new pipedinputstream(pipeout );printrstream printstream = new printsteam(pipeout );zthread zthread = new zthread(yfileln printstream );zthread start();return pipeln ;}catch(exception e){system out println(e tostring());}return null;}} Ythread類和Zthread類由於ythread類與zthread類基本一樣 在此僅以ythread為例加以說明 Ythread的構造器接收兩個參數 輸入的文件和第一個管道的輸出端 構造器存儲這兩個參數作為類的數據成員 Ythread(datainputstream xfileln pringstream printstream){this xfileln = xfileln;this printstream = printstream;} 線程通過run()方法來處理數據 首先讀取一行數據 確保xstring不為空的情況下循環執行 string xstring = xfileln readline();每讀一行數據 完成一次轉換string ystring = xstring replace( x y );然後將修改後的數據輸出到管道的輸出端 prinstream prinrln(ystring);為了確保所有緩沖區的數據完全進入管道的輸出端 pringstram flush();循環完成後 線程關閉管道輸出流 pringstram close();ythread類的源程序如下 //ythread Java//import Java io *;class ythread exteads thread{datainputstream xfileln;pringstream printstream;ythread(datainputstream xfileln pringstream printstream){this xfileln = xfileln;this printstream = printstream;}public void run(){try{string xstring = xfileln readline();while(xstring!=null){string ystring= xstring replace( x y );printstream pringln(ystring);printstream flush();xstring= xfileln readline();}printstream close();}catch{ioexception e}{system out println(e tostring());}}} pipeapp應用程序使用microsoft visual j++ 編譯 lishixin/Article/program/Java/gj/201311/27508

熱點內容
手機版伺服器生存有什麼好玩的服務 發布:2025-07-14 01:49:45 瀏覽:209
銳龍3代編程 發布:2025-07-14 01:48:22 瀏覽:967
配置管理需要會什麼 發布:2025-07-14 01:35:35 瀏覽:372
去除頭條中的緩存 發布:2025-07-14 01:27:38 瀏覽:783
php開啟錯誤 發布:2025-07-14 01:16:49 瀏覽:998
esp資料庫 發布:2025-07-14 01:16:44 瀏覽:980
python查找文件路徑 發布:2025-07-14 01:16:03 瀏覽:514
phpapachetomcat 發布:2025-07-14 01:08:41 瀏覽:123
伺服器運維看什麼書 發布:2025-07-14 01:07:32 瀏覽:988
密碼器動態密碼怎麼弄 發布:2025-07-14 00:44:27 瀏覽:386