java執行緒等待/通知機制及中斷
一、等待/通知機制
線上程互動中經常需要對其進行一些控制,希望人為地能夠讓執行緒按理想路線發展,在滿足某條件時進行執行操作而發生變化時,停止等待。
1、 使用sleep
在 if ( ) { } else { } 中使用sleep 對執行緒進行停止等待一段時間。 弊端:正常情況下 無法客觀預知需要等待的時間,在刻意睡眠一段時間後 很可能發現 依舊不適合由此執行緒執行之後的操作,或者睡眠過久。
2、 使用 while + sleep 迴圈判斷條件 使其睡眠 弊端:雖然能加快判斷條件的變化,但依舊難以確保及時性,會造成無端浪費。
3、wait +notify :在某條件發生情況下,執行緒A呼叫物件O 的wait() 方法進入等待狀態,當執行緒B呼叫物件O的notify() 或者notifyAll()方法後,執行緒A會接受通知,從其wait方法返回,執行後續操作。
java.lang.Obejct :
notify() 通知一個在物件上等待的執行緒,使其從wait方法返回(前提是該執行緒獲取到物件的鎖)
notifyAll() 通知所有等待在該物件上的執行緒 (注意,notify等通知時 不會釋放當前物件鎖)
wait() 呼叫該方法的執行緒進入Waiting狀態,只有被中斷或者由其他執行緒通知喚醒才能繼續(wait會導致執行緒釋放物件鎖)
wait(long) 超時等待一段時間,等待xx毫秒,若沒有收到通知 則超時返回
wait(long,int)超時精確到納秒
例:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
public class WaitAndNotify {
static boolean flag=true;
static Object lock =new Object();
public static void main(String[] args) throws InterruptedException {
Thread waitThread=new Thread(new Wait(),"waitThread");
waitThread.start();
TimeUnit.SECONDS.sleep(2);
Thread notifyThread=new Thread(new Notify(),"notifyThread");
notifyThread.start();
}
static class Wait implements Runnable{
@Override
public void run() {
synchronized (lock) {
//同步程式碼塊
while (flag) {
try {
System.out.println(Thread.currentThread().getName()+" flag=true. [email protected]"+
new SimpleDateFormat("HH:mm:ss").format(new Date()));
lock.wait();<span style="white-space:pre"> </span>System.out.println("啊啊?");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//跳出while時
System.out.println(Thread.currentThread().getName()+" flag=false. [email protected]"+
new SimpleDateFormat("HH:mm:ss").format(new Date()));
}
}
}
static class Notify implements Runnable{
@Override
public void run() {
synchronized (lock) {
//獲取lock物件鎖,然後通知喚醒
System.out.println(Thread.currentThread().getName()+" hold lock. [email protected]"+
new SimpleDateFormat("HH:mm:ss").format(new Date()));
lock.notifyAll();
flag=false;
try {
Thread.sleep(3000);//notify之後執行緒睡眠3秒,驗證Wait類不能馬上輸出“啊啊?”
} catch (InterruptedException e) {
e.printStackTrace();
}
} //同步程式碼塊結束後 釋放鎖
synchronized (lock) {
//再次加鎖
System.out.println(Thread.currentThread().getName()+" hold lock again. @"+
new SimpleDateFormat("HH:mm:ss").format(new Date()));
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
執行結果:(注:在notifyThread裡的兩個同步程式碼塊之間 可能會發生lock被Wait獲取 而使輸出結果的第三、四行互換)
waitThread flag=true. [email protected]:00:44
notifyThread hold lock. [email protected]:00:46
notifyThread hold lock again. @16:00:49
啊啊?
waitThread flag=false. [email protected]:00:51
waitThread 獲取到lock物件鎖,之後呼叫wait()方法進入等待佇列,而同時會釋放掉物件鎖,狀態為Waiting。 notifyThread獲取lock物件鎖後呼叫notify()方法通知一個等待執行緒(本例中僅一個等待執行緒),將其移到同步佇列,然後繼續執行自己的程式碼,當釋放掉lock物件鎖後,waitThread執行緒才有可能重新獲取lock並執行先前未完成的程式碼。 藉助《Java併發程式設計的藝術》中一圖:
注意:
1)wait() notify() notifyAll() 等使用時 需要先對呼叫的物件加鎖獲取。
2)wait()之後 執行緒由Running轉變為Waiting 將會把當前執行緒防止到物件的等待佇列。
3)並不是一旦使用notify() notifyAll() 就能實現執行緒執行wait()方法之後的程式碼段,需要等發出notify()的執行緒先釋放物件鎖然後 等待執行緒重新獲得lock鎖 才可以執行原wait()之後的操作!4)notify()方法將等待佇列中的一個等待執行緒從其中移到同步佇列中,而notifyAll()方法則是喚醒等待佇列中的所有執行緒,全部移到同步佇列,將Waiting改為Blocked
等待方:①.獲取物件鎖 ②.若條件不滿足則呼叫物件wait(),被通知後要重新判斷條件(可能會偽喚醒)③.滿足條件後執行後續操作
通知方:①.獲取物件鎖 ②.改變條件 ③.通知等待的執行緒
二、中斷及join()
interrupt()只是改變中斷狀態而已. interrupt()不會中斷一個正在執行的執行緒。這一方法實際上完成的是,給受阻塞的執行緒丟擲一箇中斷訊號,這樣受阻執行緒就得以退出阻塞的狀態。如果執行緒被Object.wait, Thread.join和Thread.sleep三種方法之一阻塞,它將接收到一箇中斷異常(InterruptedException),從而提早地終結被阻塞狀態。
join() 含義:若執行緒A執行某thread執行緒的join(),那麼當前執行緒A等待thread執行緒終止之後才能從join()返回
例: 每個執行緒呼叫前一個執行緒的join() 按順序結束操作。
import java.util.concurrent.TimeUnit;
public class Test2 {
public static void main(String[] args) throws InterruptedException {
Thread[] myThreads =new Thread[5];
Thread previous=Thread.currentThread();
for(int i=0;i<5;i++){
myThreads[i]=new Thread(new Runner(previous),i+1+" Thread");
myThreads[i].start();
previous=myThreads[i];
}
// TimeUnit.SECONDS.sleep(3);//main sleep 3s
// myThreads[3].interrupt();
TimeUnit.SECONDS.sleep(3);//main sleep 3s
System.out.println(Thread.currentThread().getName()+" terminate");
}
static class Runner implements Runnable{
private Thread aThread;
public Runner( Thread aThread) {
this.aThread=aThread;
}
@Override
public void run() {
try {
aThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" terminate");
}
}
}
執行結果:
main terminate
1 Thread terminate
2 Thread terminate
3 Thread terminate
4 Thread terminate
5 Thread terminate
若開啟// myThreads[3].interrupt(); 註釋,則會報java.lang.InterruptedException 然後先結束4、5
再結束mian 1 2 3 注:由於執行緒一直執行,在報錯的同時,已經在輸出4的語句
java.lang.InterruptedException
4 Thread terminate
at java.lang.Object.wait(Native Method)
at java.lang.Thread.join(Thread.java:1249)
at java.lang.Thread.join(Thread.java:1323)
at Test2$Runner.run(Test2.java:25)
at java.lang.Thread.run(Thread.java:745)
5 Thread terminate
main terminate
1 Thread terminate
2 Thread terminate
3 Thread terminate
相關推薦
java執行緒等待/通知機制及中斷
一、等待/通知機制 線上程互動中經常需要對其進行一些控制,希望人為地能夠讓執行緒按理想路線發展,在滿足某條件時進行執行操作而發生變化時,停止等待。 1、 使用sleep 在 if ( ) { } else { } 中使用sleep 對執行緒進行停止等待一段時間。
15-執行緒等待通知機制總結
執行緒等待通知機制總結 概述 一個執行緒的等待阻塞狀態,受另外一個執行緒控制。 Object.wait() Object.notify() 特點 必須基於特定的物件鎖synchr
執行緒等待通知機制
等待通知機制,是指一個執行緒A呼叫了物件O的wait方法進入等待狀態,而另一個執行緒呼叫了物件O的notify或者notifyAll方法,執行緒A收到通知後從物件O的wait方法返回,進而執行後續操作 方法名稱 描述 notify() 通知一個在物件上對待的
JAVA執行緒等待及喚醒案例
案例:子執行緒迴圈10次後,主執行緒迴圈5次後再讓子執行緒迴圈10次,如此重複10次,請編寫程式碼實現。 實現程式碼如下: public class ThreadBox{ private boolean flag = true; public synchronized
多執行緒等待喚醒機制
示例程式碼取自傳智播客畢向東老師25天Java基礎教程,添加了一些觀測列印程式碼,便於理解分析。對於程序分析理解純粹個人理解,剛學Java沒多久,難免有錯,僅供參考,如果大神們發現錯誤,希望能幫忙指出,也幫我走出錯誤的理解。 先貼程式碼 class Res{ String name; Str
Java執行緒池詳解及例項
前言 多執行緒的非同步執行方式,雖然能夠最大限度發揮多核計算機的計算能力,但是如果不加控制,反而會對系統造成負擔。執行緒本身也要佔用記憶體空間,大量的執行緒會佔用記憶體資源並且可能會導致Out of Memory。即便沒有這樣的情況,大量的執行緒回收也會給GC帶來很大的壓力
java中的-等待/通知機制
等待通知機制: 是指一個執行緒A呼叫了物件O的wait()方法進入等待狀態,而另一個執行緒B 呼叫了物件O的notify()或者notifyAll()方法,執行緒A收到通知後從物件O的wait()方法
java執行緒池引數說明及佇列拒絕策略
java.util.concurrent.ThreadPoolExecutor,其構造方法1: public ThreadPoolExecutor(int corePoolSize, int maximumP
java 執行緒池詳解及四種執行緒池用法介紹
java 執行緒池詳解 Executor框架是一種將執行緒的建立和執行分離的機制。它基於Executor和ExecutorService介面,及這兩個介面的實現類ThreadPoolExecutor展開,Executor有一個內部執行緒池,並提供了將任務傳遞到池中
java執行緒池ThreadPoolExecutor原理及使用
其構造方法為public class ThreadPoolExecutor extends AbstractExecutorService{<span style="white-space:pre"> </span><div class="li
Java執行緒池原始碼解析及高質量程式碼案例
引言 本文為Java高階程式設計中的一些知識總結,其中第一章對Jdk 1.7.0_25中的多執行緒架構中的執行緒池ThreadPoolExecutor原始碼進行架構原理介紹以及原始碼解析。第二章則分析了幾個違反Java高質量程式碼案例以及相應解決辦法。如有總結
多執行緒等待喚醒機制:從wait()和sleep()的差別說起
1. wait():釋放資源,釋放鎖 sleep():釋放資源,不釋放鎖 wait():Object的方法,用在同步當中,是同步鎖的方法,以鎖控制執行緒 sleep():執行緒類Thread本身的靜態方法wait(),notify(),notifyAll()方法是用在同步當
【Java執行緒】鎖機制:synchronized、Lock、Condition
http://www.infoq.com/cn/articles/java-memory-model-5 深入理解Java記憶體模型(五)——鎖 http://www.ibm.com/developerworks/cn/java/j-jtp10264/ Java 理論與
Java 執行緒池詳解及例項程式碼
這篇文章主要介紹了Java 執行緒池的相關資料,並符例項程式碼,幫助大家學習參考,需要的朋友可以參考下執行緒池的技術背景在面向物件程式設計中,建立和銷燬物件是很費時間的,因為建立一個物件要獲取記憶體資源或者其它更多資源。在Java中更是如此,虛擬機器將試圖跟蹤每一個物件,以便
多執行緒——等待-喚醒機制
package com.work.wor01; /** * 等待喚醒機制 * 涉及到了3個方法: * 1.wait():等待,將正在執行的執行緒釋放了其執行資格和執行權利,並且將他儲存到執行緒池當中。 * (執行緒池:運行當中會出現很多正在被凍結的執行緒,都會儲存到
Java併發之等待/通知機制
目錄 1 前言 1.1 先來段程式碼放鬆一下 2 Object wait()/notify() 2.1 一段入門程式碼 2.2 問題三連擊 a.為什麼官方說w
Java執行緒池詳解及常用方法
前言 最近被問到了執行緒池的相關問題。於是準備開始寫一些多執行緒相關的文章。這篇將介紹一下執行緒池的基本使用。 Executors Executors是concurrent包下的一個類,為我們提供了建立執行緒池的簡便方法。 Executors可以建立我們常用的四種執行緒池: (1)newCachedThrea
Java—執行緒的生命週期及執行緒控制方法詳解
# 執行緒生命週期5種狀態 ## 介紹 執行緒的生命週期經過**新建(New)、就緒(Runnable)、執行(Running)、阻塞(Bolocked)和死亡(Dead)** ## 狀態轉換圖 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/202005191855
Java多執行緒之三volatile與等待通知機制示例
原子性,可見性與有序性 在多執行緒中,執行緒同步的時候一般需要考慮原子性,可見性與有序性 原子性 原子性定義:一個操作或者多個操作在執行過程中要麼全部執行完成,要麼全部都不執行,不存在執行一部分的情況。 以我們在Java程式碼中經常用到的自增操作i++為例,i++實際上並不是一步操作,而是首先對i的值加一,然
java執行緒之間的通訊(等待/通知機制)
執行緒開始執行,擁有自己的棧空間,就如同一個指令碼一樣,按照程式碼一步步的執行直到終止。但是,每個執行中的執行緒,如果僅僅是孤立地執行,那麼沒有太大的價值,但如果多個執行緒能夠相互配合完成工作,這將會帶來巨大的價值。 而java多執行緒的等待和通知機制就是用來