1. 程式人生 > >同步機制中notify()與wait()--實現A,B,C迴圈列印

同步機制中notify()與wait()--實現A,B,C迴圈列印

關於同步與非同步機制,聽過很多通俗的解釋。

日常生活中其實也有很多這樣的例子,比如吃飯的時候

同步:就是你通知我去吃飯,我聽到了就和你一起去,如果我沒有迴應,你就會一直喊,直到我有反映了為止。

非同步:你通知我一聲後,不管我有沒有迴應,你自己就去吃飯去了。

在通訊當中:

同步:傳送方發出資料後,等接收方發回響應以後才發下一個數據包的通訊方式。 

非同步:傳送方發出資料後,不等接收方發回響應,接著傳送下個數據包的通訊方式。

java在實現同步機制的過程中,主要用到了兩種方法,一種是同步方法,一種是同步程式碼塊。兩種都用到了synchronized關鍵字。

同步方法:

public void sychronized study() {
        System.out.println("studying");
}
同步程式碼塊:
(sychronized){
     ......
}
說到這裡,下面說一下在同步程式碼塊中使用notify(),以及wait()來實現一個經典的執行緒列印問題--利用三個執行緒A,B,C分別各自迴圈列印A,B,C.

關於notify()以及wait(),這裡敘述一下。


我們可以看到,wait()與notify()同屬於object類的方法,由於object被所有類所繼承,所以這兩個方法也會被所有類所繼承。而且,我們看原始碼,關於兩個方法

public final native void notify();
public final void wait() throws InterruptedException {
        wait(0);
    }
兩個方法都有final修飾,則在子類中不能夠被重寫。

wait 方法:
使當前執行緒一直處於等待的狀態,直到另一個執行緒在呼叫了notify()或者notifyAll()方法。

當前執行緒擁有當前物件的鎖,即wait()方法應該在sychronized{}方法或者程式碼塊中。呼叫wait()方法後,釋放對當前物件鎖的擁有。

notify()方法:

喚醒處於等待狀態的執行緒,這裡應該注意是,如果有多個執行緒處於等待的狀態,那麼呼叫一次notify()方法後,具體釋放的是哪一個執行緒是不確定的,執行的過程是java虛擬機器來實現的。

跟wait方法一樣,notify也是必須放在synchronized方法或synchronized塊中。

關於wait()與notify()方法,利用三個執行緒迴圈列印A,B,C是很具有代表性的。

public class MyThread {
	public static void main(String[] args) throws Exception {
		Object A = new Object();
		Object B = new Object();
		Object C = new Object();

		Thread t1 = new Thread(new Print(A, B), "A");
		Thread t2 = new Thread(new Print(B, C), "B");
		Thread t3 = new Thread(new Print(C, A), "C");
                
                //Thread.sleep(1)為了讓列印的時候依次執行
		t1.start();
		Thread.sleep(1);
		t2.start();
		Thread.sleep(1);
		t3.start();

	}
}

class Print implements Runnable {

	private Object self;
	private Object next;

	public Print(Object self, Object next) throws InterruptedException {
		this.self = self;
		this.next = next;

	}

	public void run() {
		for (int i = 0; i < 10; i++) {
			synchronized (self) {
				synchronized (next) {
					System.out.println(Thread.currentThread().getName());
					next.notify();
				}
				try {
					if (i == 9) {
						return; // 當i == 9 即最後一次迴圈, 將直接退出 不再進行等待
					}
					self.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}

	}
}
列印的結果為ABCABCABCABCABCABCABCABCABCABC(當然,這裡未顯示換行符)

現在簡單的看一下程式執行的過程。

首先執行緒A(這裡為執行緒的名字)呼叫start方法,在run方法中,self為A,next為B,列印一下Thread.CurrentThread.getName()為A.然後執行self.wait(),即此時A處於阻塞狀態。然後執行緒B(執行緒的名字)進入run方法,self為B,next為C,然後先列印一下B,再執行next.notify()方法,此時把之前處於阻塞狀態的執行緒A不再阻塞。當執行下面的self.wait的時候,此時執行緒B就處於阻塞狀態了,而執行緒A,C處於就緒狀態,等待處理機的排程。然後執行緒C進入run方法,self為C,next為A,列印一下C,next.notify使之前處於阻塞的B處於就緒狀態,然後 C再進入等待的狀態,依次下去。

相關推薦

同步機制notify()wait()--實現A,B,C迴圈列印

關於同步與非同步機制,聽過很多通俗的解釋。 日常生活中其實也有很多這樣的例子,比如吃飯的時候 同步:就是你通知我去吃飯,我聽到了就和你一起去,如果我沒有迴應,你就會一直喊,直到我有反映了為止。 非同步:你通知我一聲後,不管我有沒有迴應,你自己就去吃飯去了。 在通訊當中: 同

JAVA 多執行緒使用Lock,Condition實現A,B,C,D依次執行,實現排它,同步通訊。

package com.study; import java.util.concurrent.locks.Condition

分散式站點資料同步機制的設計實現[出自別處]

摘要:在網際網路蓬勃發展的今天,把集團公司下的各個水電站的資料同步起來,統一管理的需求日益突顯。本公司首先採用了oracle公司自身提供的解決方案高階複製技術,但限於本國網速緩慢網路時常斷線的不穩定的狀態的特殊國情,實施效果不盡如人意。針對我國苛刻的網路條件,本公司努力研發,自主地設計了一套低網速資料同步系統

Java 內部類,多執行緒Synchronizedwait,notify的使用

工作內容: 1.成員內部類    與成員方法,屬性的訪問許可權一致 2.靜態內部類    修飾符 stactic 類名{...} 3.匿名內部類    new 類名()/介面名(重寫介面方法) 4.區域性內部類    程式碼塊中 5.執行緒Thread wait,noti

多執行緒同步sleepwait區別

1、函式 wait是Object的一個函式,指執行緒處於進入等待狀態,此時執行緒不佔用任何資源,不增加時間限制。wait可以被notify和notifyAll函式喚醒(這兩個也是Object的函

C#-----------------------------回收機制Destroynull的作用

icon des www ocl 技術 比較 view 情況 它的 關於Object被Destroy之後,該Object的原引用==null的問題 標簽: unityc#繼承對象 2017-01-23 23:32 506人閱讀 評論(0) 收藏 舉報 分類:

執行緒sleep()wait()的區別

對時間的指定。  1,sleep方法必須指定時間。  2,wait方法有過載形式,可以指定時間,也可以不指定時間。 對於執行權和鎖的操作.:  1,sleep():釋放執行權,不釋放鎖,因為肯定能醒,肯定可以恢復到臨時阻塞狀態。  2,wait():釋

javasleepwait的不同

1,sleep()方法是屬於Thread類中的,wait()方法是屬於Object類中的 2,sleep()方法導致了程式暫停執行指定的時間,讓出cpu,給其他執行緒,但是他的監控狀態依然保持者,當指定的時間到了又會自動恢復執行狀態。 3,在呼叫sleep()方法的過程中,執行緒不會釋放物件

生產者/消費者程式碼(使用notifywait實現

package cn.wzy.Lock; import java.util.Random; public class ConsumerAndProducer { static String[] food = new String[5]; static String take() th

Javasleepwait的區別

學習時正好碰到這兩個方法,就查閱相關資料,並通過程式實現,進行區別一下:1、每個物件都有一個鎖來控制同步訪問,Synchronized關鍵字可以和物件的鎖互動,來實現同步方法或同步塊。sleep()方法正在執行的執行緒主動讓出CPU(然後CPU就可以去執行其他任務),在sle

windows訊息機制lparamwparam兩個引數的分析

一. WPARAM 和 LPARAM 本質上沒有什麼區別:都是32位數, 但是區別也還是有的:MICROSOFT在使用時兩種引數分別代表不同的含義和內容,WPARAM常常代表一些控制元件的ID或者高位低位組合起來分別表示滑鼠的位置,如果訊息的傳送者需要將某種結構的指標或者是

Javasleep()wait()區別

學習時正好碰到這兩個方法,就查閱相關資料,並通過程式實現,進行區別一下:1、每個物件都有一個鎖來控制同步訪問,Synchronized關鍵字可以和物件的鎖互動,來實現同步方法或同步塊。sleep()方法正在執行的執行緒主動讓出CPU(然後CPU就可以去執行其他任務),在slee

LeetCode3Sum(a+b+c=0)的解法證明

這道題。開始的時候想用hash表來做,可是需要排除重複就會造成O(n3)的複雜度,也可能是我這個方法沒弄好。想了很久,也沒有做出來,在網上看了別人的解放,遂恍然大悟,但是網上沒有它解法的證明,所以在這裡寫下我的證明,以來以後看看。 原題目為: 唯一性: 這道題最關鍵的就是

Javasleep()wait()區別標記一下

學習時正好碰到這兩個方法,就查閱相關資料,並通過程式實現,進行區別一下: 1、每個物件都有一個鎖來控制同步訪問,Synchronized關鍵字可以和物件的鎖互動,來實現同步方法或同步塊。sleep()方法正在執行的執行緒主動讓出CPU(然後CPU就可以去執行其他任務),

IPv4A,B,C類網及子網掩碼那些事

來看 了解 擁有 nbsp 開發 信息 alt 位或 其余 IP 地址的主要類型有五種 A B C D 和 E 一般 A B C 類地址更為常用 每類地址都是由 32 位或 4 個字節組成 A類地址: 在 A 類地址中第一個 8 位字節表示網絡部分 其余 3 個 8 位字節

select * from A.B.C.D sqlserver select * from .Literary_PuDong.dbo.Users

class com 數據 技術 rar sqlserve data ima 擁有 服務器名.數據庫名.表擁有者(架構名).表名 服務器名(服務器IP).數據庫名.表擁有者.表名 [192.168.99.66].TEST.dbo.table1[Testdb].TEST

筆記:Java實現三個執行緒A B C,BC執行緒執行完再執行A

final Lock lc = new ReentrantLock(); .. run() { lc.lock(); ... lc.unlock(); } 可能開啟方式不對吧,沒實現! 改用join() 可以實現(BC與A以單執行緒模式執行),程式碼如下: package

java實現:2018年9月9日晚上的京東筆試題:現給出n個物品的a,b,c引數,請你求出不合格品的數量。

題目: 現有n個物品,每個物品有三個引數,ai,bi,ci,定義i物品不合格的依據是:若存在物品j,且aj>ai,bj>bi,cj>ci,則稱i物品為不合格品。 現給出n個物品的a,b,c引數,請你求出不合格品的數量。 輸入: 第一行包含一個整數n(1<=n&

基於回溯法思想:輸入一個字串,按字典序打印出該字串字元的所有排列。例如輸入字串abc,則打印出由字元a,b,c所能排列出來的所有字串abc,acb,bac,bca,cab和cba。

    連結:https://www.nowcoder.com/questionTerminal/fe6b651b66ae47d7acce78ffdd9a96c7 來源:牛客網 import java.util.List; import java.util.Col

1093 字串A+B——C++實現

題目 1093 字串A+B (20 分) 給定兩個字串 A 和 B,本題要求你輸出 A+B,即兩個字串的並集。要求先輸出 A,再輸出 B,但重複的字元必須被剔除。 輸入格式: 輸入在兩行中分別給出 A 和 B,均為長度不超過 10​6​​的、由可見 ASCII 字元