线程间的通信

线程间的通信:


  • 等待唤醒机制 -多个线程在操作同一份数据时,避免对同一变量进行争夺

    目的:有效利用资源
    重点:对资源占用的判断

TimeWaiting -计时等待


  1. 使用sleep(long m)方法,线程睡醒进入Runnable/Blocked(阻塞状态)
  2. 使用wait(long m),毫秒值结束之后,若未被唤醒,则会进入阻塞状态
  • 注:notify只会唤醒同一锁对象

    1. wait与notify必须在同步代码块或者同步方法中使用
    2. 通过锁对象调用
public class ThreadWaitNotifyAll {
    public static void main(String[] args) {
        Object obj = new Object();
        //匿名内部类创建一个线程
        new Thread("消费者线程"){
            @Override
            public void run() {
                //等待唤醒只能有一个线程进行,利用同步机制
                synchronized (obj) {
                    System.out.println("消费者:老板我要买东西,给你2s");
                    try {
                        obj.wait(2000);  //无限等待,直到被唤醒
                        System.out.println("消费者:收到了,谢谢老板,我带走了");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            }
        }.start();
        new Thread("消费者1线程"){
            @Override
            public void run() {
                //等待唤醒只能有一个线程进行,利用同步机制
                synchronized (obj) {
                    System.out.println("消费者01:老板我要买东西,给你2s");
                    try {
                        obj.wait(2000);  //无限等待,直到被唤醒
                        System.out.println("消费者01:收到了,谢谢老板,我带走了");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            }
        }.start();

        //在创建一个线程
        new Thread("老板线程"){
            @Override
            public void run() {
                //上面线程等待5s
                System.out.println("老板:谢谢你们的5s钟");

                synchronized (obj) {
                    System.out.println("老板:我做好了,来拿吧");
                    //会唤醒调度队列队头的进程 obj.notify();
                    //由于是在同步块内,此刻没锁,唤醒后会再获取锁,获取成功RUNNABLE
                    // 若没获取到,会重新进入调度队列 entry set,WAITING转为BLOCKED状态

                    //全部唤醒
                    obj.notifyAll();
                }

            }
        }.start();


    }
}

等待唤醒案例:


  1. 创建一个线程,告知另一线程需要通信,让其进入WAITING状态(无限等待)
  2. 创建一个另一线程,唤醒上一线程
  • 注:顾客和老板线程必须用同步代码块锁起来,保证有一个在执行

    1. 同步锁对象必须保证唯一
    2. 只有锁对象能调用wait()/notify()方法
  • 在Object类中

    void wait()
    在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。
    void notify()
    唤醒在此对象监视器上等待的单个线程。
    void notifyAll()
    唤醒在此对象监视器上等待的所有线程,会继续执行wait之后的方法

public class ThreadState {
    public static void main(String[] args) {
        Object obj = new Object();
        //匿名内部类创建一个线程
        new Thread("消费者线程"){
            @Override
            public void run() {
                //等待唤醒只能有一个线程进行,利用同步机制
                synchronized (obj) {
                    System.out.println("消费者:老板我要买东西");
                    try {
                        obj.wait();  //无限等待,直到被唤醒
                        System.out.println("消费者:收到了,谢谢老板,我带走了");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            }
        }.start();

        //在创建一个线程
        new Thread("老板线程"){
            @Override
            public void run() {
                //花5秒准备东西
                try {
                    System.out.println("老板:好的,等我五秒钟准备一下");
                    Thread.sleep(0000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //唤醒一个线程
                synchronized (obj) {
                    System.out.println("老板:我做好了,来拿吧");
                    obj.notify();  //唤醒上面的线程,执行wait之后的代码,但是该线程还没结束
                    //下面代码仍然在抢占cpu的执行权,因为唤醒后,当前线程还未解锁
                    System.out.println("老板:哈哈,骗你的继续等吧");
                }
                //休息会儿让上面的线程先走
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //上面线程结束
                System.out.println("老板:不客气");
            }
        }.start();


    }
}

你可能感兴趣的:(线程间的通信)