LinkedBlockingQueue生产者消费者问题?

ydm305365 2013-09-12 12:08:37


package com.duanqu.manager.service.user;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.weaver.ast.And;

import com.duanqu.common.model.MessageModel;
import com.duanqu.manager.dao.UserAdminMapper;
import com.duanqu.redis.service.syn.message.IMessageSynService;


public class ThreadSendMessage {
Log logger = LogFactory.getLog(ThreadSendMessage.class);
long num;
UserAdminMapper userAdminMapper;
IMessageSynService messageSynService;
String messageText;
BlockingQueue<Long> blockingQueue = new LinkedBlockingQueue<Long>(2000);
final int pageSize=1000;
long logNum;


public void send() {
//借用线程池
ExecutorService service = Executors.newCachedThreadPool();
//生产者
Producer producer=new Producer();

//消费者
Consumer consumer=new Consumer();
Consumer consumer2=new Consumer();
Consumer consumer3=new Consumer();
Consumer consumer4=new Consumer();
Consumer consumer5=new Consumer();
Consumer consumer6=new Consumer();
service.execute(producer);
service.execute(consumer);
service.execute(consumer2);
service.execute(consumer3);
service.execute(consumer4);
service.execute(consumer5);
service.execute(consumer6);

}

public ThreadSendMessage(long num, UserAdminMapper userAdminMapper,
IMessageSynService messageSynService, String messageText) {
this.num = num;
this.userAdminMapper = userAdminMapper;
this.messageSynService = messageSynService;
this.messageText = messageText;
}

// 消费者线程
class Consumer implements Runnable {
Long recUid;
@Override
public void run() {
while(true){
try {
/*if(blockingQueue.size()<1000){
notifyAll();
}*/
recUid=blockingQueue.poll();
if(recUid!=null){
MessageModel mm = new MessageModel();
mm.setUid(1);
mm.setMessageText(messageText);
mm.setRecUid(recUid);
mm.setCreateTime(System.currentTimeMillis());
messageSynService.synMessageSend(mm);
logNum++;
System.out.println(logNum);
if(logNum==5000){
System.out.println("已经发送了五千用户=========================");
}
if(logNum==1000){
System.out.println("已经发送了1千用户=========================");
}
if(logNum==500){
System.out.println("已经发送了500用户=========================");
}
if(logNum==2000){
System.out.println("已经发送了2千用户=========================");
}
}
} catch (Exception e) {
logger.error("发送消息失败的用户ID:"+recUid);
e.printStackTrace();

}

}
}
}
//生产者线程
class Producer implements Runnable {
@Override
public void run() {
while(true){
/*if(blockingQueue.size()>1000){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}*/
if(num>0){
Map<String, Object> map=new HashMap<String, Object>();
map.put("pageStart", (num-1)*pageSize);
map.put("pageSize", pageSize);
List<Long> list=userAdminMapper.getUserList(map);
blockingQueue.addAll(list);
num--;
}
}
}
}
}







需求是这样的,我现在要给10万用户群发私信,我写了一个生产者线程从数据库里取数据,每次取1000条然后插入LinkedBlockingQueue中,我开了六个消费者从这里读取数据然后插入redis,刚开始想使用注释的代码协调线程调度,后来报了IllegalMonitorStateException - 如果当前线程不是此对象监视器的所有者的异常,于是注释掉,打算使用队列自带的阻塞功能,我现在有一个疑问假如队列里现在有2000个数据了,生产者线程是不是会阻塞,然后等消费者消费掉,假如消费者消费掉了200个数据,这时生产者会不会自动唤醒,如果唤醒了在从数据库里拿了1000个数据,能不能放进这个队列,因为队列设定了固定大小2000个,消费掉200,还有1800个,然后这时候来了1000个数据,这时候是一个什么样的情形,,,还请多线程高手帮我出思路一般完善这段程序,感激不尽

...全文
264 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
番茄超蛋 2015-03-06
  • 打赏
  • 举报
回复
poll取的时候如果取到null说明queue空了 ,这个时候再取唤醒生产者取数据。
ydm305365 2013-09-12
  • 打赏
  • 举报
回复
一个个取出来在放是不是太慢了
tony4geek 2013-09-12
  • 打赏
  • 举报
回复
put 的时候取list 中的一个对象
ydm305365 2013-09-12
  • 打赏
  • 举报
回复
基于我这种需求有没有更好的设计思路,请各位看一下
ydm305365 2013-09-12
  • 打赏
  • 举报
回复
put不能一下放进去一个list
tony4geek 2013-09-12
  • 打赏
  • 举报
回复
LinkedBlockingQueue的put和take方法应该就行了,阻塞什么都做好了里面方法都有

62,621

社区成员

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

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