Java使用wait/notify實(shí)現(xiàn)線程間通信下篇
上一節(jié)針對(duì)wait/notify實(shí)現(xiàn)線程間通信的基本概念做了講解(Java使用wait/notify實(shí)現(xiàn)線程間通信上篇),本節(jié)繼續(xù)針對(duì)wait/notify實(shí)現(xiàn)線程間通信的其他知識(shí)點(diǎn)及特性進(jìn)行講解。
1. 當(dāng) interrupt() 方法遇到 wait() 方法
當(dāng)線程調(diào)用鎖對(duì)象的wait() 方法使線程呈等待狀態(tài)時(shí),調(diào)用線程對(duì)象的 interrupt() 方法會(huì)出現(xiàn) InterruptedException 異常。
public class ThreadC7 {
@Test
public void test1() {
try {
Object obj = new Object();
ThreadC7A threadC7A = new ThreadC7A(obj);
threadC7A.start();
Thread.sleep(2000);
threadC7A.interrupt();
} catch (Exception e) {
e.printStackTrace();
}
}
}
class ServiceC7 {
public void testMethod(Object obj) {
try {
synchronized (obj) {
System.out.println("begin wait");
obj.wait();
System.out.println("begin end");
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("出現(xiàn)異常了,wait狀態(tài)的線程被interrupt了!");
}
}
}
class ThreadC7A extends Thread {
private Object obj;
public ThreadC7A(Object obj) {
this.obj = obj;
}
@Override
public void run() {
ServiceC7 serviceC7 = new ServiceC7();
serviceC7.testMethod(obj);
}
}執(zhí)行結(jié)果:

2. notify() 只通知一個(gè)線程
調(diào)用方法notify()一次只隨機(jī)通知一個(gè)線程進(jìn)行喚醒。
public class ThreadC8 {
@Test
public void test() {
Object obj = new Object();
ThreadC8A threadC8A = new ThreadC8A(obj);
threadC8A.setName("threadC8A");
threadC8A.start();
ThreadC8B threadC8B = new ThreadC8B(obj);
threadC8B.setName("threadC8B");
threadC8B.start();
ThreadC8C threadC8C = new ThreadC8C(obj);
threadC8C.setName("threadC8C");
threadC8C.start();
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (obj) {
obj.notify();
}
while (Thread.activeCount() > 1) {
}
}
}
class ServiceC8 {
public void service(Object obj) {
try {
synchronized (obj) {
String threadName = Thread.currentThread().getName();
System.out.println("begin wait,Thread Name:[" + threadName + "]");
obj.wait();
System.out.println("end wait,Thread Name:[" + threadName + "]");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class ThreadC8A extends Thread {
private Object obj;
public ThreadC8A(Object obj) {
this.obj = obj;
}
@Override
public void run() {
ServiceC8 serviceC8 = new ServiceC8();
serviceC8.service(obj);
}
}
class ThreadC8B extends Thread {
private Object obj;
public ThreadC8B(Object obj) {
this.obj = obj;
}
@Override
public void run() {
ServiceC8 serviceC8 = new ServiceC8();
serviceC8.service(obj);
}
}
class ThreadC8C extends Thread {
private Object obj;
public ThreadC8C(Object obj) {
this.obj = obj;
}
@Override
public void run() {
ServiceC8 serviceC8 = new ServiceC8();
serviceC8.service(obj);
}
}執(zhí)行結(jié)果:

程序運(yùn)行的效果如圖所示,可以看出方法notify()僅隨機(jī)喚醒一個(gè)線程。
當(dāng)多次調(diào)用notify()方法時(shí),會(huì)隨機(jī)將等待wait狀態(tài)的線程進(jìn)行喚醒。更改代碼如下:

再次運(yùn)行,程序運(yùn)行效果如圖所示,可以看出所有的線程全部被喚醒。

多次調(diào)用notify()方法可喚醒全部WAITING中的線程。
3. notifyAll() 喚醒所有線程
前面的示例中通過(guò)多次調(diào)用 notify() 方法來(lái)實(shí)現(xiàn)喚醒3個(gè)線程,但并不能保證系統(tǒng)中僅有3個(gè)線程,也就是若notify()方法的調(diào)用次數(shù)小于線程對(duì)象的數(shù)量,會(huì)出現(xiàn)有部分線程對(duì)象無(wú)法被喚醒的情況。為了喚醒全部線程,可以使用notifyAll()方法。
更改代碼如下:

再次運(yùn)行,程序運(yùn)行效果如圖所示,可以看出所有的線程全部被喚醒。

4. 方法 wait(long)的使用
帶一個(gè)參數(shù)的wait(long) 方法的功能是等待某一時(shí)間內(nèi)是否有現(xiàn)成對(duì)鎖進(jìn)行喚醒,如果超過(guò)這個(gè)時(shí)間則自動(dòng)喚醒。
public class ThreadC9 {
@Test
public void test() {
Object obj = new Object();
ThreadC9A threadC9A = new ThreadC9A(obj);
threadC9A.start();
while (Thread.activeCount() > 1) {
}
}
}
class ThreadC9A extends Thread {
private Object obj;
public ThreadC9A(Object obj) {
this.obj = obj;
}
@Override
public void run() {
try {
synchronized (obj) {
long startTime = System.currentTimeMillis();
System.out.println("begin wait,time:[" + startTime + "]");
obj.wait(5000);
long endTime = System.currentTimeMillis();
System.out.println("end wait,time:[" + endTime + "] takes " + (endTime - startTime) + " ms");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}執(zhí)行結(jié)果:

通過(guò)執(zhí)行結(jié)果可以看出,在經(jīng)過(guò)5000ms后,線程被喚醒。
到此這篇關(guān)于Java使用wait/notify實(shí)現(xiàn)線程間通信下篇的文章就介紹到這了,更多相關(guān)Java wait notify內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
nacos配置注冊(cè)中心時(shí)指定命名空間不起作用的問(wèn)題
這篇文章主要介紹了nacos配置注冊(cè)中心時(shí)指定命名空間不起作用的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。2022-01-01
Java中@Pattern注解常用的校驗(yàn)正則表達(dá)式學(xué)習(xí)筆記
對(duì)于正則這個(gè)東西,對(duì)我來(lái)說(shuō)一直是很懵逼的,每次用每次查,然后還是記不住,下面這篇文章主要給大家介紹了關(guān)于Java中@Pattern注解常用的校驗(yàn)正則表達(dá)式學(xué)習(xí)筆記的相關(guān)資料,需要的朋友可以參考下2022-07-07
SpringBoot JPA懶加載失效的解決方案(親測(cè)有效)
這篇文章主要介紹了SpringBoot JPA懶加載失效的解決方案(親測(cè)有效),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
詳解Java Proxy動(dòng)態(tài)代理機(jī)制
今天給大家?guī)?lái)的是關(guān)于Java的相關(guān)知識(shí),文章圍繞著Java動(dòng)態(tài)代理機(jī)制展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06
Java 處理高并發(fā)負(fù)載類優(yōu)化方法案例詳解
這篇文章主要介紹了Java 處理高并發(fā)負(fù)載類優(yōu)化方法案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
Java解析http協(xié)議字符串的方法實(shí)現(xiàn)
本文主要介紹了Java解析http協(xié)議字符串的方法實(shí)現(xiàn),我們探討了如何使用Java解析HTTP協(xié)議字符串,并將其封裝成了一個(gè)HttpRequest類,具有一定的參考價(jià)值,感興趣的可以了解一下2023-09-09
springboot 如何設(shè)置端口號(hào)和添加項(xiàng)目名
這篇文章主要介紹了springboot設(shè)置端口號(hào)和添加項(xiàng)目名的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
Java數(shù)組優(yōu)點(diǎn)和缺點(diǎn)_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
本文給大家簡(jiǎn)單介紹下java數(shù)組的優(yōu)點(diǎn)和缺點(diǎn)知識(shí),需要的的朋友參考下吧2017-04-04

