線程間通訊 wait notify notifyAll

wati notify notifyAll 都是Object的方法java

常常與synchronized關鍵字配合使用ide

咱們用個列子來講明下spa

public class notifyWait {
    private static int m =0;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
       final Object lock = new Object();
     
       Thread t1 = new Thread( new Runnable(){
       
		@Override
		public void run() {
			synchronized (lock) {
				System.out.println("t1啓動..");
				// TODO Auto-generated method stub
				for (int i = 0; i < 50; i++) {
					System.out.println("當前線程:" + Thread.currentThread().getName()+"i=="+i);
					if (i == 5) {
						System.out.println("喚醒t2線程");
						lock.notifyAll();//不釋放鎖 t2線程雖然被喚醒 但 操做系統時間片任然在t1線程
					}
					m++;
				}
			}
			
		}}
       );
       
       Thread t2 = new Thread( new Runnable(){

		@Override
		public void run() {
			synchronized (lock) {
			
				// TODO Auto-generated method stub
				if (m != 5) {
                   try {
                   
					lock.wait();//等待 釋放鎖
					System.out.println("t2 啓動");//從新喚醒後外面的判斷沒影響
                   	System.out.println("t2被喚醒");
				
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
              
				}
			}
		}});
       
       t2.start();
       t1.start();
	}

}

建立t1 t2兩個線程 兩個線程啓動執行run裏面的方法時要得到 lock方法的鎖操作系統

分別啓動 t2 t1線程 代碼裏面能夠看出線程

t2線程啓動時 先得到lock鎖 而後調用 wait方法  t2線程讓出cpu執行時間 進入lock對象的休息區休息(wait方法釋放鎖)code

t1線程啓動後 知足必定條件後在lock對象上調用 notifyAll方法 喚醒在lock對象上等待的線程(notify 喚醒一個等待線程,但不肯定是哪個 ,notifyAll喚醒全部在lock對象上休眠的線程 ,我通常都使用notify方法,固然若是能肯定等待的線程只有一個也可以使用notify方法)對象

 

運行結果get

t1啓動..
當前線程:Thread-0i==0
當前線程:Thread-0i==1
當前線程:Thread-0i==2
當前線程:Thread-0i==3
當前線程:Thread-0i==4
當前線程:Thread-0i==5
喚醒t2線程
當前線程:Thread-0i==6
當前線程:Thread-0i==7
當前線程:Thread-0i==8
當前線程:Thread-0i==9
當前線程:Thread-0i==10
當前線程:Thread-0i==11
當前線程:Thread-0i==12
當前線程:Thread-0i==13
當前線程:Thread-0i==14
當前線程:Thread-0i==15
當前線程:Thread-0i==16
當前線程:Thread-0i==17
當前線程:Thread-0i==18
當前線程:Thread-0i==19
當前線程:Thread-0i==20
當前線程:Thread-0i==21
當前線程:Thread-0i==22
當前線程:Thread-0i==23
當前線程:Thread-0i==24
當前線程:Thread-0i==25
當前線程:Thread-0i==26
當前線程:Thread-0i==27
當前線程:Thread-0i==28
當前線程:Thread-0i==29
當前線程:Thread-0i==30
當前線程:Thread-0i==31
當前線程:Thread-0i==32
當前線程:Thread-0i==33
當前線程:Thread-0i==34
當前線程:Thread-0i==35
當前線程:Thread-0i==36
當前線程:Thread-0i==37
當前線程:Thread-0i==38
當前線程:Thread-0i==39
當前線程:Thread-0i==40
當前線程:Thread-0i==41
當前線程:Thread-0i==42
當前線程:Thread-0i==43
當前線程:Thread-0i==44
當前線程:Thread-0i==45
當前線程:Thread-0i==46
當前線程:Thread-0i==47
當前線程:Thread-0i==48
當前線程:Thread-0i==49
t2 啓動
t2被喚醒

這個結果代表線程 t1 在執行到i 等於5的時候 向在lock對象上休眠的對象發出了喚醒通知 並且 後面it

t2也確實被喚醒了(打印了t2啓動 t2被喚醒);io

 

如今 有一個問題 就是t1在喚醒t2後 還接着把循環打印完 而後 t2纔開始 執行實際的方法,

這是由於 notify notifyAll不釋放鎖 雖然t1 把t2喚醒了 可是 lock對象的鎖還在t1上 ,因此t1會先執行完。

也就是喚醒不及時 t2被喚醒後 沒能及時處理本身的邏輯

針對這個問題咱們能夠java.util.concurrent下的CountDownLatch來處理

public class CountDownLatchnotify {
	

    private static int m =0;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
       final Object lock = new Object();
       final CountDownLatch c = new CountDownLatch(1);
       Thread t1 = new Thread( new Runnable(){

		@Override
		public void run() {
			
				System.out.println("t1啓動..");
				// TODO Auto-generated method stub
				for (int i = 0; i < 50; i++) {
					System.out.println("當前線程:" + Thread.currentThread().getName()+"i=="+i);
					if (i == 5) {
						System.out.println("喚醒t2線程");
					    c.countDown();
					   
					}
					m++;
				}
		
			
		}}
       );
       
       Thread t2 = new Thread( new Runnable(){

		@Override
		public void run() {
	
		
				// TODO Auto-generated method stub
		
				if (m != 5) {
                  try {
					c.await();
					System.out.println("t2 啓動");
					System.out.println("t2 被喚醒");
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				}
			
		}});
       
       t2.start();
       t1.start();
	}



}

在CountDownLatch調用await方法線程進入休眠狀態 直到CountDownLatch的計數器爲0 立刻被喚醒

運行結果

t1啓動..
當前線程:Thread-0i==0
當前線程:Thread-0i==1
當前線程:Thread-0i==2
當前線程:Thread-0i==3
當前線程:Thread-0i==4
當前線程:Thread-0i==5
喚醒t2線程
當前線程:Thread-0i==6
t2 啓動
t2 被喚醒
當前線程:Thread-0i==7
當前線程:Thread-0i==8
當前線程:Thread-0i==9
當前線程:Thread-0i==10
當前線程:Thread-0i==11
當前線程:Thread-0i==12
當前線程:Thread-0i==13
當前線程:Thread-0i==14
當前線程:Thread-0i==15
當前線程:Thread-0i==16
當前線程:Thread-0i==17
當前線程:Thread-0i==18
當前線程:Thread-0i==19
當前線程:Thread-0i==20
當前線程:Thread-0i==21
當前線程:Thread-0i==22
當前線程:Thread-0i==23
當前線程:Thread-0i==24
當前線程:Thread-0i==25
當前線程:Thread-0i==26
當前線程:Thread-0i==27
當前線程:Thread-0i==28
當前線程:Thread-0i==29
當前線程:Thread-0i==30
當前線程:Thread-0i==31
當前線程:Thread-0i==32
當前線程:Thread-0i==33
當前線程:Thread-0i==34
當前線程:Thread-0i==35
當前線程:Thread-0i==36
當前線程:Thread-0i==37
當前線程:Thread-0i==38
當前線程:Thread-0i==39
當前線程:Thread-0i==40
當前線程:Thread-0i==41
當前線程:Thread-0i==42
當前線程:Thread-0i==43
當前線程:Thread-0i==44
當前線程:Thread-0i==45
當前線程:Thread-0i==46
當前線程:Thread-0i==47
當前線程:Thread-0i==48
當前線程:Thread-0i==49
相關文章
相關標籤/搜索