多线程——4线程间的通信

多线程——4线程间的通信

一、内容安排

  1. wait和notify方法
  2. 简单的生产者消费者
  3. 面试点

二、文章内容

1. wait和notify方法

​ 当一个对象调用了wait方法那么它将阻塞当前线程, 直到有另外一个线程调用了当前对象的notify方法,被阻塞的线程才可能被唤醒。

注意: 若要调用这两个方法必须先获得对象的锁,不让会抛出异常

  • 案列: 启动A、B两个线程,A线程中调用wait方法在wait之后打印”被唤醒“; 在B线程中先打印”我来唤醒“,然后调用notify方法
public static void main(String[] args) {
        //定义公用对象
        Object object = new Object();

        //线程A
        new Thread(()->{

            synchronized (object) {
                try {
                    //调用object的wait方法阻塞当前线程
                    object.wait();
                    //打印
                    System.out.println("我被唤醒了");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        //线程B
        new Thread(()->{
            System.out.println("我要唤醒A线程");
            synchronized (object) {
                try {
                    TimeUnit.SECONDS.sleep(3);
                    object.notify();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

    }

2.简单的生产者消费者

有了上面提到的wait和notify两个方法,我们可以利用这两个方法实现一个简单(生产者生产一个等待消费者消费再生产)的生产者消费者;

实现思路:

  1. 开启两个线程,一个不断的生产一个不断的消费
  2. 生产者线程生产消息之后唤醒等待中的消费者并让自己阻塞,等待消费者消费之后让消费者唤醒自己
  3. 消费者线程: 消费消息,唤醒生产者线程,然后自己阻塞

具体实现:

public class ProducerConsumer {

    static Object LOCK = new Object();
    static Boolean isProduced = false;
    static Integer i = 0;

    public static void main(String[] args) {

        // 定义生产者线程
        new Thread(() -> {
            while (true) {
                synchronized (LOCK) {
                    if (!isProduced) {
                        System.out.println("生产者生产消息" + ++i);
                        LOCK.notify();
                        isProduced = true;
                    } else {
                        try {
                            LOCK.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }, "producer").start();


        // 定义消费者线程
        new Thread(() -> {
            while (true) {
                synchronized (LOCK) {
                    if (isProduced) {
                        System.out.println("消费者生产消息" + i);
                        LOCK.notify();
                        isProduced = false;
                    } else {
                        try {
                            LOCK.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }, "consumer").start();


    }
}

3.面试考点

  • wait和sleep的区别
    1. 所属对象不同: wait是Object中的方法, sleep是Thread中的方法
    2. sleep不会释放锁,而wait会释放锁
    3. sleep可以直接使用在任何地方, 但是使用wait方法必须使用在同步带吗块儿中;并且需要使用锁对象
    4. sleep自动唤醒, wait需要别人唤醒

发布了11 篇原创文章 · 获赞 11 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/sui_feng_piao_guo/article/details/103247303