導航:首頁 > 編程語言 > java線程通信的方式

java線程通信的方式

發布時間:2023-09-22 17:22:10

java 線程間通信的幾種方式

Java多線程間的通信

Java還提供了一種線程間通信的機制,這種通信通什麼實現?
wait,notify等機制
或使用pipeInputStream和pipeOutputStream

1. 線程的幾種狀態
線程有四種狀態,任何一個線程肯定處於這四種狀態中的一種:
1) 產生(New):線程對象已經產生,但尚未被啟動,所以無法執行。如通過new產生了一個線程對象後沒對它調用start()函數之前。
2) 可執行(Runnable):每個支持多線程的系統都有一個排程器,排程器會從線程池中選擇一個線程並啟動它。當一個線程處於可執行狀態時,表示它可能正處於線程池中等待排排程器啟動它;也可能它已正在執行。如執行了一個線程對象的start()方法後,線程就處於可執行狀態,但顯而易見的是此時線程不一定正在執行中。
3) 死亡(Dead):當一個線程正常結束,它便處於死亡狀態。如一個線程的run()函數執行完畢後線程就進入死亡狀態。
4) 停滯(Blocked):當一個線程處於停滯狀態時,系統排程器就會忽略它,不對它進行排程。

Ⅱ JAVA中線程同步方法有哪些

JAVA中線程同步方法一般有以下三種:
1 wait方法:
該方法屬於Object的方法,wait方法的作用是使得當前調用wait方法所在部分(代碼塊)的線程停止執行,並釋放當前獲得的調用wait所在的代碼塊的鎖,並在其他線程調用notify或者notifyAll方法時恢復到競爭鎖狀態(一旦獲得鎖就恢復執行)。
調用wait方法需要注意幾點:
第一點:wait被調用的時候必須在擁有鎖(即synchronized修飾的)的代碼塊中。
第二點:恢復執行後,從wait的下一條語句開始執行,因而wait方法總是應當在while循環中調用,以免出現恢復執行後繼續執行的條件不滿足卻繼續執行的情況。
第三點:若wait方法參數中帶時間,則除了notify和notifyAll被調用能激活處於wait狀態(等待狀態)的線程進入鎖競爭外,在其他線程中interrupt它或者參數時間到了之後,該線程也將被激活到競爭狀態。
第四點:wait方法被調用的線程必須獲得之前執行到wait時釋放掉的鎖重新獲得才能夠恢復執行。
2 notify方法和notifyAll方法:
notify方法通知調用了wait方法,但是尚未激活的一個線程進入線程調度隊列(即進入鎖競爭),注意不是立即執行。並且具體是哪一個線程不能保證。另外一點就是被喚醒的這個線程一定是在等待wait所釋放的鎖。
notifyAll方法則喚醒所有調用了wait方法,尚未激活的進程進入競爭隊列。
3 synchronized關鍵字:
第一點:synchronized用來標識一個普通方法時,表示一個線程要執行該方法,必須取得該方法所在的對象的鎖。
第二點:synchronized用來標識一個靜態方法時,表示一個線程要執行該方法,必須獲得該方法所在的類的類鎖。
第三點:synchronized修飾一個代碼塊。類似這樣:synchronized(obj) { //code.... }。表示一個線程要執行該代碼塊,必須獲得obj的鎖。這樣做的目的是減小鎖的粒度,保證當不同塊所需的鎖不沖突時不用對整個對象加鎖。利用零長度的byte數組對象做obj非常經濟。

Ⅲ java中線程同步的幾種方法

線程同步主要有以下種方法(示例中是實現計數的功能):

1、同步方法,即使用synchronized關鍵字修飾方法,例如:

publicsynchronizedvoidadd(intc){...}

2、同步代碼塊,即有synchronized關鍵字修飾的語句塊,例如:

publicvoidaddAndGet(intc){
synchronized(this){
count+=c;
}
}

3、使用特殊域變數(volatile)實現線程同步,該方法不能保證絕對的同步。

例如:privatevolatileintcount=0;

4、使用鎖實現線程同步,例如:

privateLocklock=newReentrantLock();
publicvoidadd(intc){
lock.lock();//上鎖
try{
count+=c;
}finally{
lock.unlock();//解鎖
}
}

5、使用原子變數實現線程同步,在java的util.concurrent.atomic包中提供了創建了原子類型變數的工具類,例如:

privateAtomicIntegercount=newAtomicInteger(1);
publicvoidadd(intc){
count.addAndGet(c);
}

6、使用局部變數實現線程同步,如果使用ThreadLocal管理變數,則每一個使用該變數的線程都獲得該變數的副本, 副本之間相互獨立,這樣每一個線程都可以隨意修改自己的變數副本,而不會對其他線程產生影響。

ThreadLocal 類的常用方法

new ThreadLocal<T>() : 創建一個線程本地變數

get() : 返回此線程局部變數的當前線程副本中的值

initialValue() : 返回此線程局部變數的當前線程的"初始值"

set(T value) : 將此線程局部變數的當前線程副本中的值設置為value

示例代碼:

privatestaticThreadLocal<Integer>count=newThreadLocal<Integer>(){
@Override
protectedIntegerinitialValue(){
return1;
}
};

publicvoidadd(intc){
count.set(count.get()+c);
}

7、使用阻塞隊列實現,例如LinkedBlockingQueue,具體使用可網路LinkedBlockingQueue的用法或查看java文檔。

Ⅳ java多線程有幾種實現方法線程之間如何同步

Java多線程有兩種實現方式:一種是繼承Thread類,另一種是實現Runable介面,大同小異,推薦後者,因為實現介面的話這個類還可以實現別的介面和繼承一個類,靈活性好,若繼承Thread類之後,就無法繼承其他類了。
至於實現同步,最簡單的方法就是使用同步塊,synchronized(){語句塊}
當多個線程同時訪問到同步語句塊時,會由一個線程先獲得對象鎖,獲取對象鎖的線程執行完畢之後,釋放鎖,其他線程再次競爭鎖,一個一個通過,不存在兩個以上線程同時執行同步語句塊的情況。

Ⅳ java 進程間通訊的有幾種方法

進程間通信的方法主要有以下幾種:

(1)管道(Pipe):管道可用於具有親緣關系進程間的通信,允許一個進程和另一個與它有共同祖先的進程之間進行通信。
(2)命名管道(named pipe):命名管道克服了管道沒有名字的限制,因此,除具有管道所具有的功能外,它還允許無親緣關 系進程間的通信。命名管道在文件系統中有對應的文件名。命名管道通過命令mkfifo或系統調用mkfifo來創建。
(3)信號(Signal):信號是比較復雜的通信方式,用於通知接受進程有某種事件發生,除了用於進程間通信外,進程還可以發送 信號給進程本身;linux除了支持Unix早期信號語義函數sigal外,還支持語義符合Posix.1標準的信號函數sigaction(實際上,該函數是基於BSD的,BSD為了實現可靠信號機制,又能夠統一對外介面,用sigaction函數重新實現了signal函數)。
(4)消息(Message)隊列:消息隊列是消息的鏈接表,包括Posix消息隊列system V消息隊列。有足夠許可權的進程可以向隊列中添加消息,被賦予讀許可權的進程則可以讀走隊列中的消息。消息隊列克服了信號承載信息量少,管道只能承載無格式位元組流以及緩沖區大小受限等缺
(5)共享內存:使得多個進程可以訪問同一塊內存空間,是最快的可用IPC形式。是針對其他通信機制運行效率較低而設計的。往往與其它通信機制,如信號量結合使用,來達到進程間的同步及互斥。
(6)內存映射(mapped memory):內存映射允許任何多個進程間通信,每一個使用該機制的進程通過把一個共享的文件映射到自己的進程地址空間來實現它。
(7)信號量(semaphore):主要作為進程間以及同一進程不同線程之間的同步手段。
(8)套介面(Socket):更為一般的進程間通信機制,可用於不同機器之間的進程間通信。起初是由Unix系統的BSD分支開發出來的,但現在一般可以移植到其它類Unix系統上:Linux和System V的變種都支持套接字。

而在java中我們實現多線程間通信則主要採用"共享變數"和"管道流"這兩種方法

方法一 通過訪問共享變數的方式(注:需要處理同步問題)
方法二 通過管道流

其中方法一有兩種實現方法,即
方法一a)通過內部類實現線程的共享變數
代碼如下:

public class Innersharethread {
public static void main(String[] args) {
Mythread mythread = new Mythread();
mythread.getThread().start();
mythread.getThread().start();
mythread.getThread().start();
mythread.getThread().start();
}
}
class Mythread {
int index = 0;
private class InnerThread extends Thread {
public synchronized void run() {
while (true) {
System.out.println(Thread.currentThread().getName()
+ "is running and index is " + index++);
}
}
}
public Thread getThread() {
return new InnerThread();
}
}
/**
* 通過內部類實現線程的共享變數
*
*/
public class Innersharethread {
public static void main(String[] args) {
Mythread mythread = new Mythread();
mythread.getThread().start();
mythread.getThread().start();
mythread.getThread().start();
mythread.getThread().start();
}
}
class Mythread {
int index = 0;
private class InnerThread extends Thread {
public synchronized void run() {
while (true) {
System.out.println(Thread.currentThread().getName()
+ "is running and index is " + index++);
}
}
}
public Thread getThread() {
return new InnerThread();
}
}

b)通過實現Runnable介面實現線程的共享變數
代碼如下:

public class Interfacaesharethread {
public static void main(String[] args) {
Mythread mythread = new Mythread();
new Thread(mythread).start();
new Thread(mythread).start();
new Thread(mythread).start();
new Thread(mythread).start();
}
}
/* 實現Runnable介面 */
class Mythread implements Runnable {
int index = 0;
public synchronized void run() {
while (true)
System.out.println(Thread.currentThread().getName() + "is running and
the index is " + index++);
}
}
/**
* 通過實現Runnable介面實現線程的共享變數
*/
public class Interfacaesharethread {
public static void main(String[] args) {
Mythread mythread = new Mythread();
new Thread(mythread).start();
new Thread(mythread).start();
new Thread(mythread).start();
new Thread(mythread).start();
}
}
/* 實現Runnable介面 */
class Mythread implements Runnable {
int index = 0;
public synchronized void run() {
while (true)
System.out.println(Thread.currentThread().getName() + "is running and
the index is " + index++);
}
}

方法二(通過管道流):
代碼如下:

public class CommunicateWhitPiping {
public static void main(String[] args) {
/**
* 創建管道輸出流
*/
PipedOutputStream pos = new PipedOutputStream();
/**
* 創建管道輸入流
*/
PipedInputStream pis = new PipedInputStream();
try {
/**
* 將管道輸入流與輸出流連接 此過程也可通過重載的構造函數來實現
*/
pos.connect(pis);
} catch (IOException e) {
e.printStackTrace();
}
/**
* 創建生產者線程
*/
Procer p = new Procer(pos);
/**
* 創建消費者線程
*/
Consumer c = new Consumer(pis);
/**
* 啟動線程
*/
p.start();
c.start();
}
}
/**
* 生產者線程(與一個管道輸入流相關聯)
*
*/
class Procer extends Thread {
private PipedOutputStream pos;
public Procer(PipedOutputStream pos) {
this.pos = pos;
}
public void run() {
int i = 8;
try {
pos.write(i);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 消費者線程(與一個管道輸入流相關聯)
*
*/
class Consumer extends Thread {
private PipedInputStream pis;
public Consumer(PipedInputStream pis) {
this.pis = pis;
}
public void run() {
try {
System.out.println(pis.read());
} catch (IOException e) {
e.printStackTrace();
}
}
}
閱讀全文

與java線程通信的方式相關的資料

熱點內容
viper4android安卓60 瀏覽:485
java軟體源碼 瀏覽:159
空氣壓縮機的類型 瀏覽:352
centos圖形命令行界面切換 瀏覽:237
新京報新聞APP什麼時候有的 瀏覽:818
華為手機文件夾重命名空白 瀏覽:742
通俗理解螞蟻演算法 瀏覽:555
俠盜獵車手怎麼注冊伺服器 瀏覽:341
去商場吃飯預約什麼app 瀏覽:776
nginx不能解析php 瀏覽:135
安卓系統如何轉換中文 瀏覽:316
小米手機用什麼下載非官方app 瀏覽:760
linux修改readonly 瀏覽:32
演算法時代我們能做什麼 瀏覽:928
牛津英語搭配詞典pdf 瀏覽:284
慧連a6怎麼連接安卓 瀏覽:235
python使用什麼編譯器最好 瀏覽:52
小程序編譯藍屏 瀏覽:947
程序員賽車的gif 瀏覽:413
購買新車能用到什麼app 瀏覽:775