关于线程控制的问题

paullbm 2009-11-04 06:08:25
加精
关于线程控制的问题

已知有一个队列,希望其中的元素超过200个的时候,进行元素获取并删除(即poll)操作,然后将获取到的所有元素批量写入到数据库中。
本人现在已经用了一种线程轮询的方式实现了此功能。但考虑到CPU的利用率及程序的高并发问题,需要将线程控制方式由轮询改为触发的方式。
本人所谓的轮询即是在控制线程类ControlThread中的run方法进行无限循环,在此循环中进行队列元素个数的监视及sleep操作。
而本人希望采用的触发方式则是当队列元素个数不断增长,涨到200时,则通过发送一个信号给控制线程ControlThread,ControlThread才会进行一次run方法。
望各路高手赐教!!!谢谢!!
...全文
1535 127 打赏 收藏 转发到动态 举报
写回复
用AI写文章
127 条回复
切换为时间正序
请发表友善的回复…
发表回复
fyjava1984 2009-11-09
  • 打赏
  • 举报
回复
元素每次增长的时候 都判断一下是否超过200个元素 如果超过就调用一下poll操作
不用线程,
fqli1610 2009-11-09
  • 打赏
  • 举报
回复
每天回帖即可获得10分可用分!小技巧:教您如何更快获得可用分
郑大钱 2009-11-09
  • 打赏
  • 举报
回复
看看!学了!
冰思雨 2009-11-09
  • 打赏
  • 举报
回复
个人理解的楼主想要实现的代码:
package houlei.csdn.mutiThread.batch2DB;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;

/**
* 这个代码应该是楼主说的那个,当满200条记录时,产生一个事件。<br/>
* 然后,将事件(本例通过eventPipe)传递给处理线程,进行处理。
* <p>
* 创建时间:2009-11-9 下午09:07:07
* @author 侯磊
* @since 1.0
*/
public class EventModelAction extends AbstractDBAction implements CollectAction {
private static final int MaxSize = 200;
private List<POJO> cache = new ArrayList<POJO>(MaxSize);
private Queue<Event> eventPipe = new ArrayBlockingQueue<Event>(1);
private EventProcessor thread = new EventProcessor();
public EventModelAction(){
if(thread.running==false){
thread.running=true;thread.start();
}
}
/**
* 事件类。在本程序中,这个类纯属鸡肋。<br/>
* 旨在说明程序的框架内容。
* <p>
* 创建时间:2009-11-9 下午09:11:37
* @author 侯磊
* @since 1.0
*/
static class Event{
Collection<POJO> beans;
}

/** 将缓冲区的数据持久化。
* @see houlei.csdn.mutiThread.batch2DB.CollectAction#flush()
*/
public void flush() throws SQLException {
if(cache.size()>0){
Event e = new Event();
e.beans = cache;
eventPipe.add(e);
cache = new ArrayList<POJO>(MaxSize);
}
}

/** 持续放入待持久化的对象。
* @see houlei.csdn.mutiThread.batch2DB.CollectAction#put(houlei.csdn.mutiThread.batch2DB.POJO)
*/
public void put(POJO bean) throws SQLException {
cache.add(bean);
if(cache.size()>=MaxSize){
Event e = new Event();
e.beans = cache;
eventPipe.add(e);
cache = new ArrayList<POJO>(MaxSize);
}
}
class EventProcessor extends Thread{
private volatile boolean running = false;
public void run(){
while(running){
Event e = eventPipe.poll();
try {
fetch(e.beans);
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
}

/**
* 示例代码
*/
public static void main(String[] args) throws SQLException {
boolean hasMorePOJOs = true;
CollectAction act = new EventModelAction();
while(hasMorePOJOs){
POJO bean = new POJO(){};
act.put(bean);
}
act.flush();
}
}

我自己的想法:
package houlei.csdn.mutiThread.batch2DB;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* 如果是我,我会按照下面的思路进行处理。<br/>
* 就是使用线程池来批量更新。<p/>
* 如果就一个线程进行数据的收集,可以将synchronized去掉。
* <p>
* 创建时间:2009-11-9 下午09:23:49
* @author 侯磊
* @since 1.0
*/
public class MySimpleAction extends AbstractDBAction implements CollectAction {
private static final int MaxSize = 200;
private List<POJO> cache = new ArrayList<POJO>(MaxSize);
private static ExecutorService pool = Executors.newCachedThreadPool();

/** 将缓冲区的数据持久化。
* @see houlei.csdn.mutiThread.batch2DB.CollectAction#flush()
*/
public synchronized void flush() throws SQLException {
if(cache.size()>0){
pool.execute(new Processor(cache));
cache = new ArrayList<POJO>(MaxSize);
}
}

/** 持续放入待持久化的对象。
* @see houlei.csdn.mutiThread.batch2DB.CollectAction#put(houlei.csdn.mutiThread.batch2DB.POJO)
*/
public synchronized void put(POJO bean) throws SQLException {
cache.add(bean);
if(cache.size()>=MaxSize){
pool.execute(new Processor(cache));
cache = new ArrayList<POJO>(MaxSize);
}
}

class Processor implements Runnable{
private Collection<POJO> beans;
public Processor(Collection<POJO> beans){
this.beans=beans;
}
public void run(){
try {
fetch(beans);
} catch (SQLException e) {
e.printStackTrace();
}
}
}

/**
* 示例代码
*/
public static void main(String[] args) throws SQLException {
boolean hasMorePOJOs = true;
CollectAction act = new MySimpleAction();
while(hasMorePOJOs){
POJO bean = new POJO(){};
act.put(bean);
}
act.flush();
}
}
冰思雨 2009-11-09
  • 打赏
  • 举报
回复
想了半天。
我的理解是可能楼主由于所要持久化的数据过于庞大。
想采用批量更新的方式,提高持久化的效率。
下面写了一个样例代码。当然,旨在抛砖引玉。
有不足的地方,还请大家多多交流。
package houlei.csdn.mutiThread.batch2DB;

import java.sql.SQLException;

/**
* 对插入数据库操作的抽象。不同的实现类,采用不同的实现方式。
* <p>
* 创建时间:2009-11-9 下午08:02:16
* @author 侯磊
* @since 1.0
*/
public interface CollectAction {
/**
* 你可以把这个方法看成是向队列里插入数据对象。
*/
public abstract void put(POJO bean)throws SQLException;
/**
* 你可以理解成,如果队列里有剩余数据,通过该方法把剩余数据更新至数据库。
*/
public abstract void flush()throws SQLException;
}

package houlei.csdn.mutiThread.batch2DB;

import java.sql.SQLException;
import java.util.Collection;

/**
* 这个抽象类,其实,是要放置数据库相关的资源。
* 用于持久化操作的。
* <p>
* 创建时间:2009-11-9 下午08:15:42
* @author 侯磊
* @since 1.0
*/
public abstract class AbstractDBAction {
//这里可以放置一些数据库资源。比如:java.sql.Collection之类的东西。
/**
* 将参数集合中的所有数据,进行批量更新。
*/
public void fetch(Collection<POJO> beans)throws SQLException{
//实现数据库数据的批量更新。(楼主要求的应该是200条记录更新一次.)
}
}
package houlei.csdn.mutiThread.batch2DB;

/**
* 要存入数据库映射对象的抽象。用于举例说明。并无他用。
* <p>
* 创建时间:2009-11-9 下午08:04:04
* @author 侯磊
* @since 1.0
*/
public interface POJO {

}

最简单的情况下的代码:
package houlei.csdn.mutiThread.batch2DB;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
* 使用单一线程来完成,数据库的批量更新。<br/>
* 数据的接收、持久化都由同一线程来执行。
* 理论上不存在线程同步问题。
* <p>
* 创建时间:2009-11-9 下午08:07:40
* @author 侯磊
* @since 1.0
*/
public class SingleThreadAction extends AbstractDBAction implements CollectAction {
private static final int MaxSize = 200;
private List<POJO> cache = new ArrayList<POJO>(MaxSize);
/** 每放入MaxSize个数据对象,批量更新一次数据库。
* @see houlei.csdn.mutiThread.batch2DB.CollectAction#put(houlei.csdn.mutiThread.batch2DB.POJO)
*/
public void put(POJO bean) throws SQLException {
cache.add(bean);
if(cache.size()>=MaxSize){
fetch(cache);
cache.clear();
}
}

/** 将缓冲区的数据持久化。
* @see houlei.csdn.mutiThread.batch2DB.CollectAction#flush()
*/
public void flush() throws SQLException {
if(cache.size()>0){
fetch(cache);
cache.clear();
}
}

/**
* 示例代码
*/
public static void main(String[] args) throws SQLException {
boolean hasMorePOJOs = true;
CollectAction act = new SingleThreadAction();
while(hasMorePOJOs){
POJO bean = new POJO(){};
act.put(bean);
}
act.flush();
}
}

轮询情况下的代码:
package houlei.csdn.mutiThread.batch2DB;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;

/**
* 楼主说的轮询线程执行批量更新。
* <p>
* 创建时间:2009-11-9 下午08:35:40
* @author 侯磊
* @since 1.0
*/
public class PollThreadAction extends AbstractDBAction implements CollectAction {
private static final int MaxSize = 200;
private PollThread thread = new PollThread();
private Queue<POJO> cache = new ArrayBlockingQueue<POJO>(MaxSize+MaxSize/2);
public PollThreadAction(){
if(thread.running==false){
thread.running=true;thread.start();
}
}
/** 将缓冲区的数据持久化。
* @see houlei.csdn.mutiThread.batch2DB.CollectAction#flush()
*/
public synchronized void flush() throws SQLException {
ArrayList<POJO> list = new ArrayList<POJO>(MaxSize);
POJO bean = null;
while((bean = cache.poll())!=null){
list.add(bean);
}
fetch(list);
}

/** 持续放入待持久化的对象。
* @see houlei.csdn.mutiThread.batch2DB.CollectAction#put(houlei.csdn.mutiThread.batch2DB.POJO)
*/
public void put(POJO bean) throws SQLException {
cache.add(bean);
}

/**
* 轮询线程。每隔一个周期轮询缓冲区的大小,并批量更新。
* <p>
* 创建时间:2009-11-9 下午09:03:18
* @author 侯磊
* @since 1.0
*/
class PollThread extends Thread{
private volatile boolean running = false;
private static final long Cycle = 500;
public void run(){
while(running){
if(cache.size()>=MaxSize){
try {
ArrayList<POJO> list = new ArrayList<POJO>(MaxSize);
for(int i=0;i<MaxSize;i++){
list.add(cache.poll());
}
fetch(list);
} catch (SQLException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(Cycle);
} catch (InterruptedException e) {
}
}
}
}

/**
* 示例代码
*/
public static void main(String[] args) throws SQLException {
boolean hasMorePOJOs = true;
CollectAction act = new PollThreadAction();
while(hasMorePOJOs){
POJO bean = new POJO(){};
act.put(bean);
}
act.flush();
}
}
cnliming 2009-11-09
  • 打赏
  • 举报
回复
ding
gao11811 2009-11-09
  • 打赏
  • 举报
回复
[Quote=引用 123 楼 py330316117 的回复:]
引用 122 楼 fyjava1984 的回复:
元素每次增长的时候 都判断一下是否超过200个元素  如果超过就调用一下poll操作
不用线程,

在线程中加个if语句不行吗?
[/Quote]
程序可行,不代表实际可用哦,看看前面大家的讨论吧,一个if能解决就不至于那么长了呵
py330316117 2009-11-09
  • 打赏
  • 举报
回复
[Quote=引用 122 楼 fyjava1984 的回复:]
元素每次增长的时候 都判断一下是否超过200个元素  如果超过就调用一下poll操作
不用线程,
[/Quote]
在线程中加个if语句不行吗?
successgl 2009-11-08
  • 打赏
  • 举报
回复
不错的帖子,学习了很多东西,保留
w200618505 2009-11-08
  • 打赏
  • 举报
回复
学习~
Y310168595 2009-11-08
  • 打赏
  • 举报
回复

那C#中为什么没有并行控制啊 ??
Java2King 2009-11-08
  • 打赏
  • 举报
回复
学习贴
天津陈沧海 2009-11-08
  • 打赏
  • 举报
回复
正在学习中
sunchen891229 2009-11-07
  • 打赏
  • 举报
回复
线程,现在初学看不是很懂
97095639 2009-11-07
  • 打赏
  • 举报
回复
继续顶
dreanight 2009-11-07
  • 打赏
  • 举报
回复
路过,看看,
longzhen88 2009-11-07
  • 打赏
  • 举报
回复
顶一个!
kevin_alcatel 2009-11-07
  • 打赏
  • 举报
回复
路过。

学习中。。。。。。。。。。。。。
lgm277531070 2009-11-07
  • 打赏
  • 举报
回复
mark
晴天1999 2009-11-07
  • 打赏
  • 举报
回复
初学者
加载更多回复(103)

62,621

社区成员

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

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