java进阶—线程间通信(通俗易懂等待唤醒机制)

今天我们来看一看,线程之间的通信,也就是我们所说的等待唤醒机制

先来看三个关键方法:

wait();

当线程执行这个方法,它就会进入阻塞状态,并且释放同步监视器

notify();

英文翻译 唤醒,就是说会唤醒wait的线程,注意一点,是唤醒别人,不是唤醒自己,A进入wait 状态 ,需要 B 执行notify 方法去唤醒A,很好理解,你睡着了,不能自己叫醒自己,得闹钟或者别人叫醒你,自然醒那是 sleep()、

如果有多个线程进入阻塞状态,就会唤醒优先级较高的线程

notifyAll();

加了个all,唤醒全部,所有被阻塞的线程全部唤醒

这边举一个通俗的例子:不知道大家小时候有没有玩过 类似 ”全国人民大解放“ 的游戏 ,一个小朋友抓,其他跑,快要被抓住,喊出什么话(这边具体是什么忘了),就不能动了(这边类似你进入wait),得等到别人来拍你,(一般都是会先拍比较厉害的那一个)你才能动 (这边类似notify,别人来唤醒你) ,当仅剩下一个小伙伴在活动,就可以喊出 “全国人民大解放” ,所有人都可以活动(这就类似 notifyAll)

到这,应该对于等待唤醒机制比较了解了

直接上代码,通过代码我们来看看是怎么一回事

比如:

模拟两个线程进行交替打印1-10

首先我们来看看线程没有进行通信,两个线程进行资源抢占的情况:


public class Demo  implements Runnable{
    int  num = 1;

    @Override
    public void run() {
       while (true) {
           synchronized (this) {
               if (num<=10) {
                   System.out.println(Thread.currentThread().getName()+":"+num);
                   num++;
               } else {
                   break;
               }
           }

       }
    }


    public static void main(String[] args) {
            Demo demo =new Demo();
            Thread thread1 =new Thread(demo,"线程1");
            Thread thread2 =new Thread(demo,"线程2");
            thread1.start();
            thread2.start();
    }
}

java进阶—线程间通信(通俗易懂等待唤醒机制)_第1张图片
可以看到所有资源都被线程1抢占,不符合我们的需求

接下来看看两个线程间进行通信后的结果


public class Demo  implements Runnable{
    int  num = 1;

    @Override
    public void run() {
       while (true) {
           synchronized (this) {
               notify();
               if (num<=10) {
                   System.out.println(Thread.currentThread().getName()+":"+num);
                   num++;
                   try {
                       //使线程进入阻塞
                       wait();
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               } else {
                   break;
               }
           }

       }
    }


    public static void main(String[] args) {
            Demo demo =new Demo();
            Thread thread1 =new Thread(demo,"线程1");
            Thread thread2 =new Thread(demo,"线程2");
            thread1.start();
            thread2.start();
    }
}

java进阶—线程间通信(通俗易懂等待唤醒机制)_第2张图片
java进阶—线程间通信(通俗易懂等待唤醒机制)_第3张图片
线程间通信就引出了一个生产者,消费者的问题

就比如去饭店吃饭,得有饭才能去吃

生产者:Productor


public class Productor  implements Runnable{

    List<String> list  = new ArrayList<>();

    public Productor(List<String> list) {
        this.list = list;
    }


    @Override
    public void run() {
        int num = 0;
        while (true) {
            synchronized (list) {
                if (list.size() == 0) {
                    num++;
                    //没有饭生产
                    list.add("第" + num + "份米饭");
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "生产了" + list.get(0));
                    list.notify();
                } else {
                    // 有饭等待消费者消费
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            }
        }
    }
}

消费者:


public class Consumer  implements Runnable{

    List<String> list;

    public Consumer(List<String> list) {
        this.list = list;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (list) {
                if (list.size() > 0) {
                    //有饭消费,并通知生产者
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "消费了" + list.get(0));
                    list.remove(0);
                    list.notify();
                } else {
                    //无饭等待
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

进行创建线程

 public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        Productor productor =new Productor(list);
        Consumer consumer =new Consumer(list);

        new Thread(productor,"小红").start();
        new Thread(consumer,"小明").start();

    }

输出结果:

java进阶—线程间通信(通俗易懂等待唤醒机制)_第4张图片
以上就是等待唤醒机制的全部内容了

java进阶—线程间通信(通俗易懂等待唤醒机制)_第5张图片
java进阶—多线程

java 进阶—线程的常用方法

java进阶—线程安全问题

Java 进阶—死锁造成原因及其解决

你可能感兴趣的:(java基础,java,开发语言)