经过前面几节的学习,了解了多线程概念、Thread类的应用、多线程数据同步存在的问题及解决方法。本节给出一个并发编程实例应用案例,通过案例的学习,可以灵活地把多线程知识应用到实际编程中,解决在项目开发过程中遇到的并发编程问题。
在进入案例之前,先了解一下实现Java同步机制的几个方法,Java.lang.object类提供了wati()、notify()、notifyAll()方法,它们与synchronized关键字结合使用,可以建立很多优秀的同步模型。
当synchronized修饰的方法或代码块中的wati()方法被调用时,当前线程将被中断运行,并且放弃该对象的锁。
当另外的线程执行了某个对象的notify()方法后,会唤醒在此对象等待池中的某个线程,使之成为可运行的线程。notifyAll()方法会唤醒所有等待这个对象的线程,使之成为可运行的线程。
下面来看一个比较经典的问题:生产者(Producer)和消费者(Consumer)问题。这个问题的解决就是通过灵活使用wati()、notify()、notifyAll()方法来实现的。
任务要求如下:
生产者将产品交给店铺,消费者从店铺取走产品,店铺一次只能存储固定数量的产品,如果生产者生产了过多产品,店铺会让生产者等一下,如果店中有空间存储产品了,再通知生产者继续生产;如果店中没有产品了,店铺会告诉消费者等一下,如果店中有产品了,再通知消费者来取走产品。
要实现上述任务要求,我们需要定义一个生产者线程类和消费者线程类。再建立一个全局数组作为存储产品的缓冲区。其控制过程是,生产者向缓冲区存入产品,消费者从缓冲区取走产品。当缓冲区满时,生产者必须阻塞,等待消费者取走产品后将其唤醒。当缓冲区空时,消费者被阻塞,等待生产者生产了产品后将其唤醒。
定义产品类,产品包含一个产品标识的id属性。另外要在生产或消费时打印产品的详细内容,因此重写toString()方法,产品类的代码如下所示: