java 與作業系統同步問題(三)————父親兒子女兒水果問題
問題描述:父親每次都會放一個水果在桌子上,女兒喜歡吃香蕉(只吃香蕉), 兒子喜歡吃蘋果(只吃蘋果)。父親每次只會隨機往桌子上放一個水果(蘋果或香蕉),兒子,女兒會來取。使用p、v操作來完成父親、兒子、女兒的同步行為模擬。
問題分析:由上述描述我們可以知道,桌子就是一個緩衝區(單緩衝),同一時刻,只能有一個人對它進行放和取得操作。所以桌子就是一個互斥訊號量。而桌子上有蘋果,且父親沒有放,兒子才能取,女兒也是同理。所以應該還有兩個資源訊號量:1 蘋果 2 香蕉
在由題意分析可知,三個訊號量的初始值應該為 1 0 0 因為桌子只能放一個水果。而在開始的時候,桌子上是空的(所以可以進行放的操作),所以蘋果、香蕉初始資源量都為空。
程式碼實現:
1.訊號量設定如下:
/** * 緩衝區是否滿訊號量 */ Semaphore empty; /** * 蘋果訊號量 */ Semaphore apple; /** * 香蕉訊號量 */ Semaphore banana; empty = new Semaphore(1); apple = new Semaphore(0); banana = new Semaphore(0);
2.父親的放的執行緒,只有在桌子互斥資源量可以用的時候才能進行放的操作。所以要先p一下桌子訊號量。
Thread fatherThread = new Thread(new Runnable() { String className = "father"; @Override public void run() { // TODO Auto-generated method stub while(true) { Semaphore.Wait(empty, className); if (randomAB()) { System.out.println(className+ "往盤子裡放了一個蘋果"); Semaphore.Signal(apple, className); } else { System.out.println(className + "往盤子裡放了一個香蕉"); Semaphore.Signal(banana, className); } System.out.println(className + "完成了一次放的操作"); //隨機生成休眠時間,代表放入產品的操作時間 long millis = (long) (Math.random() * 1000); try { Thread.sleep(millis); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } });
3.兒子的實現,要判斷是否有蘋果,沒有的話就等待
Thread sonThread = new Thread(new Runnable() { String className = "son"; @Override public void run() { // TODO Auto-generated method stub while(true) { Semaphore.Wait(apple, className); System.out.println(className + "從盤子裡取了一個蘋果"); //隨機生成休眠時間,代表放入產品的操作時間 long millis = (long) (Math.random() * 1000); try { Thread.sleep(millis); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(className + "吃了一個蘋果"); Semaphore.Signal(empty, className); System.out.println(className + "完成了一次取吃的操作"); } } });
4.女兒的程式碼實現:原理跟兒子的類似
Thread daughterThread = new Thread(new Runnable() { String className = "daughter"; @Override public void run() { // TODO Auto-generated method stub while(true) { Semaphore.Wait(banana, className); System.out.println(className + "從盤子裡取了一個香蕉"); //隨機生成休眠時間,代表放入產品的操作時間 long millis = (long) (Math.random() * 1000); try { Thread.sleep(millis); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(className + "吃了一個香蕉"); Semaphore.Signal(empty, className); System.out.println(className + "完成了一次取吃的操作"); } } });
執行結果如下:
daughter被阻塞
son被阻塞
father往盤子裡放了一個香蕉
father資源量足夠,喚醒一個
father完成了一次放的操作
daughter從盤子裡取了一個香蕉
daughter吃了一個香蕉
daughter完成了一次取吃的操作
daughter被阻塞
father往盤子裡放了一個香蕉
father資源量足夠,喚醒一個
father完成了一次放的操作
daughter從盤子裡取了一個香蕉
father被阻塞
daughter吃了一個香蕉
daughter資源量足夠,喚醒一個
daughter完成了一次取吃的操作
....
相關推薦
java 與作業系統同步問題(三)————父親兒子女兒水果問題
問題描述:父親每次都會放一個水果在桌子上,女兒喜歡吃香蕉(只吃香蕉), 兒子喜歡吃蘋果(只吃蘋果)。父親每次只會隨機往桌子上放一個水果(蘋果或香蕉),兒子,女兒會來取。使用p、v操作來完成父親、兒子、女兒的同步行為模擬。 問題分析:由上述描述我們可以知道,桌子就是一個緩衝區(單緩衝),同一時刻,只能有
JAVA線程同步 (三)信號量
ole 給定 如何 package 分配 exec 大量 復制代碼 離開 一個信號量有且僅有3種操作,且它們全部是原子的:初始化、增加和減少 增加可以為一個進程解除阻塞; 減少可以讓一個進程進入阻塞。 信號量維護一個許可集,若有必要,會在獲得許可之前阻塞每一個線程:
Java與Highcharts例項(三)
上一回,我們使用官方的介紹,完成了Highcharts的入門 1. 引入Highcharts 依賴的JS 2. 新建DIV容器 3. 編寫JS 在這裡,我們用Java做後臺實現資料的傳遞 1. 改造JS 我們為了使用從後臺傳過來的資料,需要對JS做些修改 <scri
類與接口(三)java中的接口與嵌套接口
strong span class .... 定義 成員 抽象 數列 多個 一、接口 1. 接口簡介 接口: 是java的一種抽象類型,是抽象方法的集合。接口比抽象類更加抽象的抽象類型。 接口語法: [修飾符] [abstract] interface 接口名 [exten
Java常用的八種排序演算法與程式碼實現(三):桶排序、計數排序、基數排序
三種線性排序演算法:桶排序、計數排序、基數排序 線性排序演算法(Linear Sort):這些排序演算法的時間複雜度是線性的O(n),是非比較的排序演算法 桶排序(Bucket Sort) 將要排序的資料分到幾個有序的桶裡,每個桶裡的資料再單獨進行排序,桶內排完序之後,再把桶裡的
讀書筆記《深入理解Java虛擬機器》 (三)物件已死?與記憶體分配策略
物件是否可回收 引用計數演算法 給物件新增一個引用計數器,每當有一個地方引用它時,計數器值就加1;當引用失效時就減1;當等於0時就認為物件不可能再被使用。問題:當兩個物件相互引用時,就無法回收了。 可達性分析演算法 通過一系列的稱為“GC Roots”的物件作為起
Java多執行緒(三)、執行緒同步
在之前,已經學習到了執行緒的建立和狀態控制,但是每個執行緒之間幾乎都沒有什麼太大的聯絡。可是有的時候,可能存在多個執行緒多同一個資料進行操作,這樣,可能就會引用各種奇怪的問題。現在就來學習多執行緒對資料訪問的控制吧。 由於同一程序的多個執行緒共享同一片儲存空間,在帶來方便
Java基礎之File類與IO流(三)
一、記憶體流 使用記憶體流的需求: 把一個網路上的圖片儲存到陣列中,但是圖片的大小不能確定,怎樣解決? 記憶體流主要用來操作記憶體 ByteArrayInputStream和ByteArrayOutputStream 輸入和輸出可以把檔案作為
java面向對象(三)理論
ont def 三種 類的繼承 設置 一定的 命名 類型 以及 面向對象的基本特性 封裝 封裝性就是盡可能的隱藏對象內部細節,對外形成一道邊界,只保留有限的接口和方法與外界進行交互。封裝的原則是使對象以外的部分不能隨意的訪問和操作對象的內部屬性,從而避免了外界對對象內部
java高級工程師(三)
基礎 自信心 分布式緩存 基於 nlog 知識點 個人理解 數據 有時 一、獨白 之前也面試別人,現在輪到自己找工作,怎麽說呢,每個面試官的看法不一樣,面試的方式就不一樣,比如我面試別人我喜歡問項目中他用到了那些,然後針對用到的技術去問一些問題,或者說對於某些場景
容器與Docker簡介(三)Docker相關術語——微軟微服務電子書翻譯系列
進程 數據 public 圖像 over 表示 -c ice ner 本節列出了在更加深入Docker之前應該熟悉的術語和定義。 有關詳細的定義,請參閱Docker提供的術語表。 容器鏡像(Container image):具有創建容器所需要的所有依賴和信息的包。 鏡像
使用Eclipse + Maven 構建Java Web 項目(三)
項目打包 img app ima jet col tty class con 使用Jetty Maven 插件和Tomcat Maven 插件 1. Jetty Maven 插件 pom配置如下 <build> <finalName>we
java並發基礎(三)
線程生命周期 over out 處理請求 生命 inter 方式 希望 stat 第6章開始是第二部分,講解結構化並發應用程序,大多數並發應用程序都是圍繞“任務執行”構造的,任務通常是一些抽象的且離散的工作單元。 一、線程池 大多數服務器應用程序都提供了一種自然的任務邊界:
Java多線程(三)SimpleDateFormat
spa bsp sdf java多線程 ext add println turn static 多線程報錯:java.lang.NumberFormatException: multiple points SimpleDateFormat是非線程安全的,在多線程情況下會有
多線程編程學習筆記——線程同步(三)
class gen hybird 進行 syn locks finall nal nbsp 接上文 多線程編程學習筆記——線程同步(一) 接上文 多線程編程學習筆記——線程同步(二) 七、使用Barrier類
java編程基礎(三)流程控制語句
數據類型 char 格式 條件 -i es2017 else語句 運算 編程 流程控制語句 1.順序語句: 語句:使用分號分隔的代碼成為一條語句。 註意:沒有代碼,只有一個分號也是一條語句。 順序語句就是按照從上到下的順序依次執行的語句 2. if判斷語句 if語句
深入理解Java內存模型(三)——順序一致性
內存空間 寫入 方便 語言 body 一半 同步 java語言 post 本文轉自:http://www.infoq.com/cn/articles/java-memory-model-3 數據競爭與順序一致性保證 當程序未正確同步時,就會存在數據競爭。java內存模型規範
java 基礎歸納總結(三)
indexof set方法 返回值 substr 成員變量 bstr con 子類 數組 一、面向對象 面向對象的三大特征: 1、封裝:將類的屬性私有化 並對外提供公共的 getset方法 2、繼承:用新類繼承已有類 可以直接使用 已有類的公共的方法和屬性
Docker入門與應用系列(三)容器管理
輸出 clear tag 程序 ipaddr one 停止 1.2 標準 一、啟動容器 啟動容器有兩種方式,一種是基於鏡像新建一個容器並啟動,另一個是將終止狀態的容器重新啟動。 1.1 新建並啟動 主要命令為 docker run 下面的命令輸出一個&rd
Java Web開發總結(三) —— request接收表單提交中文參數亂碼問題
字符串 public servlet 參數 byte[] 解決 操作 get span 1、以POST方式提交表單中文參數的亂碼問題 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"