生产者消费者应用实例

kekeemx 2009-09-10 10:06:39
很久没有怎么写过多线程模型的东西了.刚好 最近修改了一个异步逻辑的时候, 将之前的线程轮询方式修改为 等待-通知 形式, 经过简单测试, 其吞吐量得到了非常大的提升. 现不敢独享,分享之, 以飨读者.同时也好做一个知识的回顾.

先简单介绍一下业务逻辑, 很简单, 每个生产逻辑线程在 得到一个需要待处理的数据之后, 封装之并作为一个对象塞入到一个 业务对象池中.(下文我们对这些线程, 称之为生产者)

然后另外一个(或者多个)消费线程不断的轮询这个 业务对象池, 看是否存在未处理对象, 若有就提取一个出来做相应的处理并从池中清除. 如果没有,则线程会sleep一会儿.(下文我们对这种线程, 称之为消费者)

这个轮询的模型在业务量比较小的时候是没有问题的,而且实现也很简单.但是如果生产者涌入数量非常多而且非常快, 这个时候消费者的处理能力就会急剧下降.


 轮询方式的模型:

共享的对象池 pool , 标黑的为synchronzied同步块.

消费者:

while (true) {

Object obj = null; // 待处理对象
synchronized (pool ) {
if (pool .size() >= 1) {
obj = pool.get(0); // 对象池中提取一个待处理对象.例如list就是remove(0)
} else {
obj = null;
}
}
if (obj == null) {
Thread.sleep(10); // 如果没有, 则会暂停一会儿. 统一为10ms
} else {
doSomething(obj); // 处理这个对象
}

}


生产者:

synchronized (pool ) {
pool .add(object); // 塞入一个待处理的对象.
}



等待-通知模型:

消费者:

while (true) {
Object obj = null;

synchronized (pool ) {
while (pool .size() <= 0) { // 注意这里必须用while而不能用if 判断,否则会产生所谓的 虚假唤醒 (spurious wakeup)。
pool .wait(); // 等待通知
}
obj = pool .get(0);
}
doSomething(obj); // 如果不放心这里还可以为空判断, 但是理论上应该不可能出现.(pool中没有空对象的话)
}


生产者:

			
synchronized (pool ) {
pool .add(input);
pool .notify(); // 唤醒等待的线程
}


经过测试.在生产者和消费者都较多的情况下, 等待-通知模型比轮询方式吞吐量是具有数量级的优势的, 但是当都很小的时候这两种方式的区别并不大, 这个是可以理解的.毕竟等待的线程被唤醒之后也是需要平等的同其他线程 一起来争取对 对象池pool的使用权, 同时我也发现, 在 标准的生产者-消费者模型中, 其系统吞吐量比目前这种等待-通知模型的吞吐量又提升了一个数量级. 开始的时候稍微有点迷惑, 后来简单想想,其实这样也对, 在标准的模型中,每当消费者发现没有数据的时候.会立即通知生产者进行生产, 两者之间是主动的. 而在实际业务模式中,没有用户访问我们的系统, 也就无从生产数据了. 是一个被动的过程. 所以其吞吐量比较低也是可以理解的.

...全文
220 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
kekeemx 2009-09-10
  • 打赏
  • 举报
回复
附 一个标准的生存者消费者模型:


static final Pool pool // 需要同步访问的共享资源

// 生产者代码
… produce() {

while(true) {

synchronized(pool ){
pool.add(object) // 产生一些东西,放到 pool 共享资源中

pool .notify(); //然后通知消费者
pool .wait(); // 然后自己进入pool待召队列
}
}
}

// 消费者代码
… consume() {

while(true) {

synchronized(pool ){
while(condition is notTrue){ // 必须使用while判断条件是否满足.
pool .wait(); // 进入pool 待召队列,等待生产者的通知
}
// 读取pool 共享资源里面的东西并做一些逻辑处理操作
pool .getObject();

pool .notify(); // 然后通知生产者
}
}
}

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧