欲善编程,多看、多敲、多讨论;动眼、动手、动大脑。
1 主要流程
在多线程的开发过程中,最为著名的案例就是生产者与消费者操作模式。其中生产者线程负责信息内容的生产,每当生产者生产完一项完整的信息后,消费者从生产者那里取走一条信息。如果生产者没有生产完,消费者等待生产消息,一旦生产完后,立马再消费消息;如果消费者没有消费消息,生产者等待消费者消费消息,消费完后再生产新消息。
注意,消费者消费完消息后,要通知生产者停止等待,抓紧生产消息;生产者生产完消息后,要通知消费者,抓紧消费消息。基础模型如下图。
2 数据同步机制
由于多线程运行的不确定性,为了避免消息的不一致,导致异常的情况,我们需要通过synchronized对消息的生产和消费进行同步。主要同步Message类中的消息set方法和get方法。
3 等待与唤醒机制
等待与唤醒机制依靠的是万事万物皆对象的Object类中提供的wait()方法和notify()或者notifyAll()方法。
小编为你避坑,wait方法如果不传参,就是死等。也可以传参,设置等待时间。当有若干个线程等待的时候,notify唤醒的是第一个等待的线程,而其他的线程继续等待;而notifyAll方法会唤醒所有等待线程,哪个线程优先级高,就有可能先执行。
4 代码实战
创建一个MessageThreadDemo类,先创建一个内部消息对象,class Message。定义title和content两个属性,消息的标题和内容。再创建set和get方法,set和get方法加上synchronize同步锁。创建两个线程,一个线程轮流生成好消息和坏消息;一个线程负责消费消息。代码及测试结果如下。
从控制台可以看到,消息重复生成和重复取出。在消息生成之前,还取出了很多空消息。这可不是我们想要的。那么接下来就可以用到上面讲到的等待与唤醒机制了。
对Message类进行改造,在message类中增加一个消息生产状态标识state,默认为false,代表消息为未生产。在set方法中,如果状态为false,则开始生产消息,生产完后通知消费线程消费,如果状态为true,则进如等待状态。代码及测试结果如下。
从测试结果可以看到,有序被生产和被消费。
5 结束语
人人都是程序员,感谢您的阅读,欢迎关注。
领取专属 10元无门槛券
私享最新 技术干货