线程间通讯 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
相关文章
相关标签/搜索