最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java線程間通信的通俗解釋及代碼示例

 更新時間:2017年11月20日 09:37:35   作者:愛折騰的貓  
這篇文章主要介紹了java線程間通信的通俗解釋,介紹了線程通信中的幾個相關(guān)概念,然后分享了線程通信的實現(xiàn)方式及代碼示例,具有一定參考價值 ,需要的朋友可以了解下。

線程間通信:由于多線程共享地址空間和數(shù)據(jù)空間,所以多個線程間的通信是一個線程的數(shù)據(jù)可以直接提供給其他線程使用,而不必通過操作系統(tǒng)(也就是內(nèi)核的調(diào)度)。

進程間的通信則不同,它的數(shù)據(jù)空間的獨立性決定了它的通信相對比較復雜,需要通過操作系統(tǒng)。以前進程間的通信只能是單機版的,現(xiàn)在操作系統(tǒng)都繼承了基于套接字(socket)的進程間的通信機制。這樣進程間的通信就不局限于單臺計算機了,實現(xiàn)了網(wǎng)絡通信。線程通信主要分為以下幾個部分,下面通過生活中圖書館借書的例子簡單講解以下:

通過共享對象通信

加入圖書館只有一本《java并發(fā)編程實戰(zhàn)》,小A早上的時候把這本書給借走了,然后下午小B去圖書館去找這本書,這時候小A和小B是兩個線程,《java并發(fā)編程實戰(zhàn)》就是共享對象(類似于多線程中的全局變量的資源),小B發(fā)現(xiàn)這本書已經(jīng)被借走了,所以就回去等了幾天,幾天后,小B又去圖書館發(fā)現(xiàn)這本書被還回來了,就把書借走了,這就是通過共享對象進行通信。

忙等待

由于快要BAT實習生招聘了,所以小B非常想看這本書,所以小B就每隔一個小時(while循環(huán))就去看看這本書有沒有被還回來了,這樣雖然比較耗費處理器資源,但是只要書一旦被還回來,小B就可以馬上知道。

wait() notify() notifyAll()

由于圖書館隔著宿舍比較近,所以小B發(fā)現(xiàn)每隔一個小時就去圖書館身體有點吃不消,不過很快,學校的圖書館系統(tǒng)增加了短信提醒功能(notify()),所以小B可以一邊睡覺一邊等短信。

丟失的信號

圖書館系統(tǒng)是這么設計的,當有一本書被還回來的時候,就會給等待者發(fā)短信,但是短信只能發(fā)送一次,如果沒有等待者,短信也會發(fā)出(只不過這個時候沒有沒有接受者),問題出現(xiàn)了,因為短信只會發(fā)一次,當書被還回來的時候,沒有人等待借書,他會發(fā)一條空短信,但是之后有等待借此本書的同學永遠也不會再收到短信,導致這些同學會無休止的等待。為了解決這個問題,我們要進入等待狀態(tài)的時候先打電話問問圖書館阿姨是否需要繼續(xù)等待。

假喚醒

圖書館系統(tǒng)有一個bug,會是不是給用戶發(fā)送錯誤短信,我們很聽話,收到短信就會去圖書館借書,但是到達圖書館后發(fā)現(xiàn)書根本就沒有被還回來,然后接著做其他的事情。

線程間的通信方式

#鎖機制:包括互斥鎖、條件變量、讀寫鎖

*互斥鎖提供了以排他方式防止數(shù)據(jù)結(jié)構(gòu)被并發(fā)修改的方法。

*讀寫鎖允許多個線程同時讀共享數(shù)據(jù),而對寫操作是互斥的。

*條件變量可以以原子的方式阻塞進程,直到某個特定條件為真為止。對條件的測試是在互斥鎖的保護下進行的。條件變量始終與互斥鎖一起使用。

#信號量機制(Semaphore):包括無名線程信號量和命名線程信號量

#信號機制(Signal):類似進程間的信號處理

線程間的通信目的主要是用于線程同步,所以線程沒有像進程通信中的用于數(shù)據(jù)交換的通信機制。

我覺得我對線程通信的理解還是不夠徹底,下面分享幾段代碼,幫助理解:

①同步

這里講的同步是指多個線程通過synchronized關(guān)鍵字這種方式來實現(xiàn)線程間的通信。

參考示例:

public class MyObject {
	synchronized public void methodA() {
		//do something....
	}
	synchronized public void methodB() {
		//do some other thing
	}
}
public class ThreadA extends Thread {
	private MyObject object;
	//省略構(gòu)造方法
	@Override
	 public void run() {
		super.run();
		object.methodA();
	}
}
public class ThreadB extends Thread {
	private MyObject object;
	//省略構(gòu)造方法
	@Override
	 public void run() {
		super.run();
		object.methodB();
	}
}
public class Run {
	public static void main(String[] args) {
		MyObject object = new MyObject();
		//線程A與線程B 持有的是同一個對象:object
		ThreadA a = new ThreadA(object);
		ThreadB b = new ThreadB(object);
		a.start();
		b.start();
	}
}

由于線程A和線程B持有同一個MyObject類的對象object,盡管這兩個線程需要調(diào)用不同的方法,但是它們是同步執(zhí)行的,比如:線程B需要等待線程A執(zhí)行完了methodA()方法之后,它才能執(zhí)行methodB()方法。這樣,線程A和線程B就實現(xiàn)了通信。

這種方式,本質(zhì)上就是“共享內(nèi)存”式的通信。多個線程需要訪問同一個共享變量,誰拿到了鎖(獲得了訪問權(quán)限),誰就可以執(zhí)行。

②while輪詢的方式

代碼如下:

import java.util.ArrayList;
import java.util.List;
public class MyList {
	private List<String> list = new ArrayList<String>();
	public void add() {
		list.add("elements");
	}
	public int size() {
		return list.size();
	}
}
import mylist.MyList;
public class ThreadA extends Thread {
	private MyList list;
	public ThreadA(MyList list) {
		super();
		this.list = list;
	}
	@Override
	 public void run() {
		try {
			for (int i = 0; i < 10; i++) {
				list.add();
				System.out.println("添加了" + (i + 1) + "個元素");
				Thread.sleep(1000);
			}
		}
		catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
import mylist.MyList;
public class ThreadB extends Thread {
	private MyList list;
	public ThreadB(MyList list) {
		super();
		this.list = list;
	}
	@Override
	 public void run() {
		try {
			while (true) {
				if (list.size() == 5) {
					System.out.println("==5, 線程b準備退出了");
					throw new InterruptedException();
				}
			}
		}
		catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
import mylist.MyList;
import extthread.ThreadA;
import extthread.ThreadB;
public class Test {
	public static void main(String[] args) {
		MyList service = new MyList();
		ThreadA a = new ThreadA(service);
		a.setName("A");
		a.start();
		ThreadB b = new ThreadB(service);
		b.setName("B");
		b.start();
	}
}

在這種方式下,線程A不斷地改變條件,線程ThreadB不停地通過while語句檢測這個條件(list.size()==5)是否成立 ,從而實現(xiàn)了線程間的通信。但是這種方式會浪費CPU資源。之所以說它浪費資源,是因為JVM調(diào)度器將CPU交給線程B執(zhí)行時,它沒做啥“有用”的工作,只是在不斷地測試 某個條件是否成立。就類似于現(xiàn)實生活中,某個人一直看著手機屏幕是否有電話來了,而不是: 在干別的事情,當有電話來時,響鈴通知TA電話來了。關(guān)于線程的輪詢的影響

③wait/notify機制

代碼如下:

import java.util.ArrayList;
import java.util.List;
public class MyList {
	private static List<String> list = new ArrayList<String>();
	public static void add() {
		list.add("anyString");
	}
	public static int size() {
		return list.size();
	}
}
public class ThreadA extends Thread {
	private Object lock;
	public ThreadA(Object lock) {
		super();
		this.lock = lock;
	}
	@Override
	 public void run() {
		try {
			synchronized (lock) {
				if (MyList.size() != 5) {
					System.out.println("wait begin "
					    + System.currentTimeMillis());
					lock.wait();
					System.out.println("wait end "
					    + System.currentTimeMillis());
				}
			}
		}
		catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
public class ThreadB extends Thread {
	private Object lock;
	public ThreadB(Object lock) {
		super();
		this.lock = lock;
	}
	@Override
	 public void run() {
		try {
			synchronized (lock) {
				for (int i = 0; i < 10; i++) {
					MyList.add();
					if (MyList.size() == 5) {
						lock.notify();
						System.out.println("已經(jīng)發(fā)出了通知");
					}
					System.out.println("添加了" + (i + 1) + "個元素!");
					Thread.sleep(1000);
				}
			}
		}
		catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
public class Run {
	public static void main(String[] args) {
		try {
			Object lock = new Object();
			ThreadA a = new ThreadA(lock);
			a.start();
			Thread.sleep(50);
			ThreadB b = new ThreadB(lock);
			b.start();
		}
		catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

線程A要等待某個條件滿足時(list.size()==5),才執(zhí)行操作。線程B則向list中添加元素,改變list的size。

A,B之間如何通信的呢?也就是說,線程A如何知道list.size()已經(jīng)為5了呢?

這里用到了Object類的wait()和notify()方法。

當條件未滿足時(list.size()!=5),線程A調(diào)用wait()放棄CPU,并進入阻塞狀態(tài)。---不像②while輪詢那樣占用CPU

當條件滿足時,線程B調(diào)用notify()通知線程A,所謂通知線程A,就是喚醒線程A,并讓它進入可運行狀態(tài)。

這種方式的一個好處就是CPU的利用率提高了。

但是也有一些缺點:比如,線程B先執(zhí)行,一下子添加了5個元素并調(diào)用了notify()發(fā)送了通知,而此時線程A還執(zhí)行;當線程A執(zhí)行并調(diào)用wait()時,那它永遠就不可能被喚醒了。因為,線程B已經(jīng)發(fā)了通知了,以后不再發(fā)通知了。這說明:通知過早,會打亂程序的執(zhí)行邏輯。

④管道通信就是使用java.io.PipedInputStream和java.io.PipedOutputStream進行通信

具體就不介紹了。分布式系統(tǒng)中說的兩種通信機制:共享內(nèi)存機制和消息通信機制。感覺前面的①中的synchronized關(guān)鍵字和②中的while輪詢“屬于”共享內(nèi)存機制,由于是輪詢的條件使用了volatile關(guān)鍵字修飾時,這就表示它們通過判斷這個“共享的條件變量“是否改變了,來實現(xiàn)進程間的交流。

而管道通信,更像消息傳遞機制,也就是說:通過管道,將一個線程中的消息發(fā)送給另一個。

總結(jié)

以上就是本文關(guān)于java線程間通信的通俗解釋的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站:

Java線程同步Lock同步鎖代碼示例

Java創(chuàng)建與結(jié)束線程代碼示例

Java編程中實現(xiàn)Condition控制線程通信

如有不足之處,歡迎留言指出。

相關(guān)文章

  • 關(guān)于RequestMapping注解的作用說明

    關(guān)于RequestMapping注解的作用說明

    這篇文章主要介紹了關(guān)于RequestMapping注解的作用說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教。
    2022-01-01
  • SpringBoot如何使用自定義注解實現(xiàn)接口限流

    SpringBoot如何使用自定義注解實現(xiàn)接口限流

    這篇文章主要介紹了SpringBoot如何使用自定義注解實現(xiàn)接口限流,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Java實現(xiàn)經(jīng)典游戲復雜迷宮

    Java實現(xiàn)經(jīng)典游戲復雜迷宮

    這篇文章主要介紹了如何利用java語言實現(xiàn)經(jīng)典《復雜迷宮》游戲,文中采用了swing技術(shù)進行了界面化處理,感興趣的小伙伴可以動手試一試
    2022-02-02
  • Java 關(guān)于eclipse導入項目發(fā)生的問題及解決方法(推薦)

    Java 關(guān)于eclipse導入項目發(fā)生的問題及解決方法(推薦)

    下面小編就為大家分享一篇Java 關(guān)于eclipse導入項目發(fā)生的問題及解決方法(推薦),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12
  • 在IDEA中配置Maven鏡像的最新方法

    在IDEA中配置Maven鏡像的最新方法

    這篇文章主要給大家介紹了關(guān)于在IDEA中配置Maven鏡像的最新方法,Maven是一個流行的Java項目構(gòu)建工具,它依賴于互聯(lián)網(wǎng)上的Mave中央倉庫來下載和管理項目依賴庫,文中通過圖文介紹的非常詳細,需要的朋友可以參考下
    2023-11-11
  • 全網(wǎng)最全SpringBoot集成swagger的詳細教程

    全網(wǎng)最全SpringBoot集成swagger的詳細教程

    swagger是當下比較流行的實時接口文文檔生成工具,swagger分為swagger2?和swagger3兩個常用版本,二者區(qū)別不是很大,主要對于依賴和注解進行了優(yōu)化,swagger2需要引入2個jar包,swagger3只需要一個,用起來沒有什么大的區(qū)別,本文給大家詳細介紹,感興趣的朋友一起看看吧
    2022-08-08
  • Spring Cache的使用示例詳解

    Spring Cache的使用示例詳解

    SpringCache是構(gòu)建在SpringContext基礎(chǔ)上的緩存實現(xiàn),提供了多種緩存注解,如@Cachable、@CacheEvict、@CachePut等,本文通過實例代碼介紹了Spring Cache的使用,感興趣的朋友一起看看吧
    2025-01-01
  • 使用socket實現(xiàn)網(wǎng)絡聊天室和私聊功能

    使用socket實現(xiàn)網(wǎng)絡聊天室和私聊功能

    這篇文章主要介紹了使用socket實現(xiàn)網(wǎng)絡聊天室和私聊功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • Java模擬實現(xiàn)HashMap算法流程詳解

    Java模擬實現(xiàn)HashMap算法流程詳解

    在java開發(fā)中,HashMap是最常用、最常見的集合容器類之一,文中通過示例代碼介紹HashMap為啥要二次Hash,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2023-02-02
  • Spring Boot中如何使用斷路器詳解

    Spring Boot中如何使用斷路器詳解

    這篇文章主要給大家介紹了關(guān)于Spring Boot中如何使用斷路器的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-08-08

最新評論

邢台市| 新密市| 新津县| 浦县| 大同市| 黄梅县| 衡水市| 广丰县| 略阳县| 视频| 东兰县| 简阳市| 同江市| 泰宁县| 汤阴县| 雅江县| 景洪市| 新源县| 江达县| 萨迦县| 湖州市| 光泽县| 运城市| 陵水| 个旧市| 江安县| 武夷山市| 铜鼓县| 铜山县| 山阴县| 贡觉县| 杭州市| 申扎县| 民和| 日喀则市| 株洲县| 虎林市| 当雄县| 广灵县| 桦甸市| 筠连县|