使用线程通信完成交替打印1-100
实现原理
实现线程间的交替打印主要是通过wait()和notify()两个方法。下面我们来讲一下几个相关方法的作用
注:以下3个方法都必须在同步代码块或同步方法中调用,否则会抛出java.lang.IllegalMonitorStateException异常
- wait():一旦执行该方法,当前线程就会进入阻塞状态,并释放同步监视器(意味着其他线程可以进入)。
- notify():一旦执行该方法,就会唤醒一个wait的线程,如果有多个线程wait,则唤醒优先级最高的那个。
- notifyAll():一旦执行该方法,会唤醒所有被wait的线程。
实现代码
1 | package com.example.socket.multithreading; |
分析代码执行过程
注:以下描述的同步监视器等同于锁
我们以A、B来代替代码中的两个线程,首先两个线程其他,假设A抢到了CPU执行权,则执行run方法,首先线程A调用notify()方法,此时没有线程wait,所以不会唤醒任何线程,然后A打印出1,并执行num++,最后线程A调用wait()方法。此时线程A进入阻塞状态,释放同步监视器,线程B可以拿到锁。然后线程B调用notify()方法唤醒线程A,由于锁没释放,所以线程A暂时不能执行。最后线程B调用wait()方法,进入阻塞状态,释放同步监视器。然后线程A可以拿到锁,执行相应代码,如此循环往复就会出现交替打印的效果。
sleep与wait方法有什么区别?
相同点
执行这两个方法后都会使线程进入阻塞状态
不同点
- sleep方法声明在Thread类中,而wait方法声明咋Object类当中。
- sleep方法可以在任意场景当中调用,而wait方法只能在同步代码块或同步方法中调用。
- sleep方法调用后不会释放同步监视器,而wait方法调用后会释放同步监视器。
生产者消费者问题
问题描述
生产者和消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一个存储空间,生产者往存储空间中添加产品,消费者从存储空间中取走产品,当存储空间为空时,消费者阻塞,当存储空间满时,生产者阻塞。
实现代码
1 | package com.example.socket.multithreading; |
该段代码实现原理基本与交替打印类似,不再详述。