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