线程wait()之后是如何执行?notify和notifyall有什么区别
wait(),notify(),notifyall()这三种方法是在多线程学习过程中常遇到的,到底他们之间有什么区别呢?
其实这三个方法主要是涉及到多线程之间的通信问题
wait()方法是让运行的线程进行等待,和Thread.sleep()方法的区别是前者一旦触发wait(),此线程将会被放进等待池或者是等待队列中进行等待唤醒,唤醒之前会一直处于等待状态,之后的程序将不会运行。后者的作用是让等待的线程处于等待一段时间,也可以称为是有效期,一旦过了有效期线程会继续执行下去。为了更好的说明问题特借用抢票模式代码进行模拟验证如下:
1.首先写一个线程类:
public class TicketThread implements Runnable { int num=0;//抢到第几张票 int count=1000;//剩余多少张 @Override public void run() { while (true){ synchronized (this){ if(count==0){ break; } notifyAll(); num++; count--; System.out.println(Thread.currentThread().getName()+"抢到第"+num+"张,剩余"+count+"张"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } try { wait(); System.out.println(Thread.currentThread().getName()+"dengdai");//重点跟踪这一句打印的位置,来分析线程等待之后的运行状态与否 } catch (InterruptedException e) { e.printStackTrace(); } } } } }
2.测试线程运行
public static void main(String[] args) { TicketThread thread = new TicketThread(); Thread t1 = new Thread(thread); Thread t2 = new Thread(thread); Thread t3 = new Thread(thread); t1.setName("lili"); t2.setName("kjl"); t3.setName("MOP"); t1.start(); t2.start(); t3.start(); }
其中一共开启了三个线程,运行结果如下:
分析:从线程运行结果来看,首先三个线程都有机会抢到票,因为他们都处于线程等待状态,根据CPU进行随机分配,所以出现了开始三个线程分别抢到票的情况,但每次抢到票的线程都会被wait()进去排队,于是System.out.println(Thread.currentThread().getName()+"dengdai");并未执行,所以控制台也并未打印出来。
由于每个线程进来后都执行了一个通知 notifyAll();所以当第二个线程进入时,第一个线程就会被唤醒了,已经有了机会进行抢资源锁,一旦被唤醒的线程抢到资源锁时,就会继续执行wait()后面的方法,并且开始进行抢票操作,也就是说被唤醒的线程抢到锁后的执行顺序应该是如图所示:
notify()和notifyall()方法其实很好理解,前者是唤醒等待线程中的某一个线程,具体哪一个有随机性,后者的作用是唤醒等待线程中的所有线程,如果等待队列中只有一个线程,那么两个方法使用效果是一样的,如果等待队列中有多个线程,那么前者只会唤醒其中给一个,而后者会唤醒所有的等待线程。
注:上面内容为自己的一点心得体会,有错误之处希望各位老司机指正!谢谢!