線程的基本協作和生產者消費者

協作基礎(wait/notify)

Java的根父類是Object,Java在Object類而非Thread類中,定義了一些線程協作的基本方法,使得每個對象都可以調用這些方法,這些方法有兩類,一類是wait,另一類是notify。

wait方法主要有兩個:

public final void wait() throws InterruptedException
public final native void wait(long timeout) throws InterruptedException;

一個帶時間參數,單位是毫秒,表示最多等待這么長時間,參數為0表示無限期等待。一個不帶時間參數,表示無限期等待,實際就是調用wait(0)。在等待期間都可以被中斷,如果被中斷,會拋出InterruptedException。

wait實際上做了什么呢?每個對象都有一把鎖和一個鎖等待隊列,一個線程在進入synchronized代碼塊時,會嘗試獲取鎖,獲取不到的話會把當前線程加入等待隊列中。其實,除了用于鎖的等待隊列,每個對象還有另一個等待隊列,表示條件隊列,該隊列用于線程間的協作。調用wait就會把當前線程放到條件隊列上并阻塞,表示當前線程執行不下去了,它需要等待一個條件,這個條件它自己改變不了,需要其他線程改變。當其他線程改變了條件后,應該調用Object的notify方法:

public final native void notify();
public final native void notifyAll();

notify做的事情就是從條件隊列中選一個線程,將其從隊列中移除并喚醒,notifyAll和notify的區別是,它會移除條件隊列中所有的線程并全部喚醒。

wait/notify方法只能在synchronized代碼塊內被調用,如果調用wait/notify方法時,當前線程沒有持有對象鎖,會拋出異常java.lang.IllegalMonitorStateException。

wait的具體過程是:

    1. 把當前線程放入條件等待隊列,釋放對象鎖,阻塞等待,線程狀態變為WAITING或TIMED_WAITING
    2. 等待時間到或被其他線程調用notify/notifyAll從條件隊列中移除,這時,要重新競爭對象鎖
      • 如果能夠獲得鎖,線程狀態變為RUNNABLE,并從wait調用中返回
      • 否則,該線程加入對象鎖等待隊列,線程狀態變為BLOCKED,只有在獲得鎖后才會從wait調用中返回

線程從wait調用中返回后,不代表其等待的條件就一定成立了,它需要重新檢查其等待的條件,一般的調用模式是:

synchronized (obj) {while (條件不成立)obj.wait();... // 條件滿足后的操作
}

?

生產者/消費者模式

下面來看一個生產者和消費者的例子:

/*** @author 沉默哥* */
public class MyProducerConsumerDemo {static class GoodsQueue {private int size;private Queue<String> que = new ArrayDeque<String>();public GoodsQueue(int size) {// 維護一個有界隊列,傳入隊列的最大容量super();this.size = size;}public synchronized void put(String e) throws InterruptedException {while (que.size() == size) {System.out.println("隊列已滿,生產者等待");wait();}que.add(e);System.out.println("生產者生產:" + e);notify();}public synchronized String take() throws InterruptedException {while (que.size() == 0) {System.out.println("隊列為空,消費者等待");wait();}String e = que.poll();System.out.println("消費者消費" + e);notify();return e;}}static class Producer extends Thread {GoodsQueue que;Random rad = new Random();public Producer(GoodsQueue que) {super();this.que = que;}@Overridepublic void run() {int i = 0;try {while (true) {String e = String.valueOf(i);que.put(e);i++;Thread.sleep(rad.nextInt(1000));// 生產者休息準備下一次生產
        }} catch (InterruptedException e1) {}}}static class Consumer extends Thread {GoodsQueue que;Random rad = new Random();public Consumer(GoodsQueue que) {super();this.que = que;}@Overridepublic void run() {try {while (true) {que.take();Thread.sleep(rad.nextInt(1000));// 消費者休息準備下一次消費
        }} catch (InterruptedException e) {}}}public static void main(String[] args) throws InterruptedException {GoodsQueue que = new GoodsQueue(1);Producer pro = new Producer(que);Consumer con = new Consumer(que);con.start();Thread.sleep(500);pro.start();}
}

?

?

轉載于:https://www.cnblogs.com/JackPn/p/9426366.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/249786.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/249786.shtml
英文地址,請注明出處:http://en.pswp.cn/news/249786.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

L1-016 查驗身份證

L1-016 查驗身份證 &#xff08;15 分&#xff09;一個合法的身份證號碼由17位地區、日期編號和順序編號加1位校驗碼組成。校驗碼的計算規則如下&#xff1a; 首先對前17位數字加權求和&#xff0c;權重分配為&#xff1a;{7&#xff0c;9&#xff0c;10&#xff0c;5&#xff…

什么是高并發,如何避免高并發

之前我將高并發的解決方法誤認為是線程或者是隊列可以解決&#xff0c;因為高并發的時候是有很多用戶在訪問&#xff0c;導致出現系統數據不正確、丟失數據現象&#xff0c;所以想到 的是用隊列解決&#xff0c;其實隊列解決的方式也可以處理&#xff0c;比如我們在競拍商品、轉…

.sync 修飾符的理解

正常 子組件&#xff1a; this.$emit(update:title, newTitle)父組件&#xff1a; <text-documentv-bind:title"doc.title"v-on:update:title"doc.title $event" ></text-document>簡潔&#xff1a; <text-document v-bind:title.sync&quo…

L1-025 正整數A+B

題的目標很簡單&#xff0c;就是求兩個正整數A和B的和&#xff0c;其中A和B都在區間[1,1000]。稍微有點麻煩的是&#xff0c;輸入并不保證是兩個正整數。 輸入格式&#xff1a; 輸入在一行給出A和B&#xff0c;其間以空格分開。問題是A和B不一定是滿足要求的正整數&#xff0c;…

到底多大才算高并發?

一、什么是高并發 定義&#xff1a; 高并發(High Concurrency)是使用技術手段使系統可以并行處理很多請求。關鍵指標&#xff1a; -響應時間(Response Time) -吞吐量(Throughput) -每秒查詢率QPS(Query Per Second) -每秒事務處理量TPS(Transaction Per Second) -同時在…

eclipse安裝maven插件

1、在線安裝插件 a.打開eclipse&#xff0c;菜單“Help”-“Install New Software...” b.在Work with 地址欄輸入&#xff1a;http://download.eclipse.org/releases/對應eclipse版本名稱 c.在filter框中輸入maven d.選擇“Collaboration”-“m2e - Maven Integration for Ecl…

VS2017 網站打包發布生成的文件中包含.pdb文件,解決辦法

右鍵點擊項目屬性&#xff0c;選擇打包/發布 Web&#xff0c;勾選 排除生成的調試符號&#xff1a; 再次發布&#xff0c;就不會再生成.pdb文件 轉載于:https://www.cnblogs.com/JoinLet/p/10297254.html

java分布式學習路線

先理解為什么需要分布式&#xff0c;因為服務器處理的能力需要提升&#xff0c;這里有兩個方面&#xff0c;第一是縱向 也就是增加cpu的能力&#xff0c;或者加內存&#xff1b;另一個方向就是 橫向 &#xff0c;就是分布式。將本來一臺計算機的壓力分給多太計算機&#xff0c;…

深入Nginx之《常用參數配置技巧》

常見參配置實戰技巧 下面會講解實戰中應該怎么配置更為合理。 1.user 默認是nobody&#xff0c;如果使用nobody&#xff0c;Nginx在運行過程中會出現很多操作沒有權限&#xff0c;比如寫硬盤。一般都是用低于root級別的用戶&#xff0c;比如www&#xff0c;并且可以在linux下設…

transform、transition 動畫效果

transform 轉換&#xff0c;變形 origin 定義旋轉基點&#xff08;left top center right bottom 坐標值&#xff09; transform-origin: 50px 50px; transform-origin: left;。 rotate 旋轉 transform:rotate(50deg) 旋轉角度可以為負數&#xff0c;需要先定義…

eslint 規則

"off"或0- 關閉規則 "warn"或1- 將規則作為警告打開&#xff08;不影響退出代碼&#xff09; "error"或2- 將規則作為錯誤打開&#xff08;觸發時退出代碼為1&#xff09;轉載于:https://www.cnblogs.com/smzd/p/10844161.html

分布式學習路線

由于分布式系統所涉及到的領域眾多&#xff0c;知識龐雜&#xff0c;很多新人在最初往往找不到頭緒&#xff0c;不知道從何處下手來一步步學習分布式架構。 本文試圖通過一個最簡單的、常用的分布式系統&#xff0c;來闡述分布式系統中的一些基本問題。 負載均衡分布式緩存分…

洛谷p2704 炮兵陣地

典型的狀態壓縮題&#xff0c;只是要定義dp[i][j][k]&#xff0c; #include<bits/stdc.h>using namespace std;int n,m,state[1<<10],tot0;int dp[110][66][66],sum[1<<10],mp[110];int getsum(int x){ int cnt0; while(x){ if(x&1) cnt; …

Flask 框架app = Flask(__name__) 解析

1 #!/usr/local/bin/python2 # codingutf-83 4 from flask import Flask5 app Flask(__name__)6 7 app.route(/)8 def hello_world():9 return Hello World! 10 11 if __name__ __main__: 12 app.run(host0.0.0.0,port9000) 第4行&#xff0c;引入Flask類&#x…

發布訂閱

發布訂閱 在軟件架構中&#xff0c;發布訂閱是一種消息范式&#xff0c;消息的發送者&#xff08;稱為發布者&#xff09;不會將消息直接發送給特定的接收者&#xff08;稱為訂閱者&#xff09;。而是將發布的消息分為不同的類別&#xff0c;無需了解哪些訂閱者&#xff08;如果…

ps 命令

ps 為我們提供了進程的一次性的查看&#xff0c;它所提供的查看結果并不動態連續的&#xff1b;如果想對進程時間監控&#xff0c;應該用 top 工具。kill 命令用于殺死進程。linux上進程有5種狀態: 1. 運行(正在運行或在運行隊列中等待) 2. 中斷(休眠中, 受阻, 在等待某個條件的…

python練習題-day8

1、有如下文件&#xff0c;a1.txt&#xff0c;里面的內容為&#xff1a; 老男孩是最好的培訓機構&#xff0c; 全心全意為學生服務&#xff0c; 只為學生未來&#xff0c;不為牟利。 我說的都是真的。哈哈 分別完成以下的功能&#xff1a; a,將原文件全部讀出來并打印。 with o…

消息中間件應用場景

消息中間件應用場景

IDEA開發vue.js卡死問題

在執行cnpm install后會在node_modules這個文件下面生成vue的相關依賴文件&#xff0c; 這個時候當執行cnpm run dev命令時&#xff0c;會導致IDEA出現卡死的問題&#xff0c;解決方法如下&#xff1a; 轉載于:https://www.cnblogs.com/heqiuyong/p/10301925.html

[BZOJ4698][SDOI2008]Sandy的卡片(后綴自動機)

差分之后就是求多串LCS。 對其中一個串建SAM&#xff0c;然后把其它串放在上面跑。 對SAM上的每個狀態都用f[x]記錄這個狀態與當前串的最長匹配長度&#xff0c;res[x]是對每次的f[x]取最小值。答案就是res[]的最大值。 考慮f[x]的求法&#xff0c;把s[]放在SAM上跑時&#xff…