1. 程式人生 > >java執行緒等待/通知機制及中斷

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多執行緒的等待和通知機制就是用來