文章目录
多线程之 wait() 和 notifyAll() 方法
wait()
-
wait的方法是让当前线程进入等待状态,并且让当前线程释放对象锁。
-
wait() 方法必须在同步代码块中使用,当我们调用wait而没有适当的锁的时候就会抛出 IllegalMonitorStateException异常。
例如我们执行这个代码的时候
public class AboutWait { public static void main(String[] args) throws InterruptedException { AboutWait.class.wait(); } }
-
当我们在加锁的同步代码块中使用wait() ,就会释放这个对象锁,让其他线程去抢占对象锁。而自己将会阻塞到这里,等待唤醒。
notifyAll()方法
- notifyAll() 和 notify() 方法都是可以唤醒调用了wait()方法而陷入阻塞的线程,但是notify()是随机唤醒这个阻塞队列中随机的一个线程,而notifyAll()是唤醒所用的调用了wait()方法而陷入阻塞的线程,让他们自己去抢占对象锁。
- notifyAll() 和 notify() 也都是必须在加锁的同步代码块中被调用,它们起的是唤醒的作用,不是释放锁的作用,只用在当前同步代码块中的程序执行完,也就是对象锁自然释放了,notifyAll() 和 notify()方法才会起作用,去唤醒线程。
- wait()方法一般是和notify() 或者 notifyAll() 方法一起连用的
使用wait()和notifytAll()方法来解决生产者消费者问题
-
有一个仓库最多存储 600 件物品, 消费者每次最多消费一件, 生产者有10个 每次生产3个,一天最多生产30次。
package lesson8; public class ProduceAndConsume { /** * 仓库现有总量 * */ public static int COUNT = 0; /** * 仓库最大容量 */ public static int MAXCOUNT = 600; /** * 几个生产者 */ public static int PRODUCERS = 10; /** * 生产者每次生产几件 */ public static int PRODUCENUM = 3; /** * 生产者最多生产几次 */ public static int PRODUCETEST = 30; /** * 几个消费者 */ public static int CONSUMER = 20; /** * 消费者每次消费多少 */ public static int CONSUMENUM = 1; /** * 生产者 生产 */ public static class produce implements Runnable { @Override public void run() { for (int i = 0; i < PRODUCETEST; i++) { // 加锁 保证原子性 try { synchronized (ProduceAndConsume.class) { while (COUNT + PRODUCENUM > MAXCOUNT) { ProduceAndConsume.class.wait(); } System.out.print("仓库有" + COUNT + "件," + "生产者生产了" + PRODUCENUM + "件"); COUNT += PRODUCENUM; System.out.println("仓库现有" + COUNT + "件"); ProduceAndConsume.class.notifyAll(); Thread.sleep(100); } Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } /** * 消费者消费 */ public static class consume implements Runnable { @Override public void run() { // 消费者只要有就消费 while (true) { try { synchronized (ProduceAndConsume.class) { while (COUNT == 0) { ProduceAndConsume.class.wait(); } System.out.print("仓库有" + COUNT + "件," + "消费者了" + CONSUMENUM + "件"); COUNT -= CONSUMENUM; System.out.println("仓库现有" + COUNT + "件"); ProduceAndConsume.class.notifyAll(); Thread.sleep(100); } Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) { Thread[] cs = new Thread[PRODUCERS]; for (int i = 0; i < PRODUCERS; i++) { cs[i] = new Thread(new produce()); } for (Thread t: cs) { t.start(); } Thread[] pd = new Thread[CONSUMER]; for (int i = 0; i < CONSUMER; i++) { pd[i] = new Thread(new consume()); } for (Thread t: pd) { t.start(); } } }
wait() 和 sleep()的区别
- 执行wait() 方法之前需要请求锁,wait()方法执行的时候会释放锁,等待被唤醒的时候竞争锁。
- sleep()只是让当前线程休眠一段时间,无视锁的存在。
- wait() 是Object类的方法 sleep()是Thread的静态方法