线程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();
}

其中一共开启了三个线程,运行结果如下:

线程wait()之后是如何执行?notify和notifyall有什么区别_第1张图片

分析:从线程运行结果来看,首先三个线程都有机会抢到票,因为他们都处于线程等待状态,根据CPU进行随机分配,所以出现了开始三个线程分别抢到票的情况,但每次抢到票的线程都会被wait()进去排队,于是System.out.println(Thread.currentThread().getName()+"dengdai");并未执行,所以控制台也并未打印出来。

由于每个线程进来后都执行了一个通知 notifyAll();所以当第二个线程进入时,第一个线程就会被唤醒了,已经有了机会进行抢资源锁,一旦被唤醒的线程抢到资源锁时,就会继续执行wait()后面的方法,并且开始进行抢票操作,也就是说被唤醒的线程抢到锁后的执行顺序应该是如图所示:

线程wait()之后是如何执行?notify和notifyall有什么区别_第2张图片

notify()和notifyall()方法其实很好理解,前者是唤醒等待线程中的某一个线程,具体哪一个有随机性,后者的作用是唤醒等待线程中的所有线程,如果等待队列中只有一个线程,那么两个方法使用效果是一样的,如果等待队列中有多个线程,那么前者只会唤醒其中给一个,而后者会唤醒所有的等待线程。

注:上面内容为自己的一点心得体会,有错误之处希望各位老司机指正!谢谢! 

你可能感兴趣的:(多线程)