生产者-消费者的 批量工作线程工具类

大并发操作数据库, 多次插入比较耗费资源, 故使用生产者-消费者模型做了这个工具

实现功能

1.队列中缓存MAX_TASK_COUNT个任务, 如果超过这个数目, 开始批量工作, 如插入到数据库

2.队列中如果一直没有放入任务,   在FORCE_WORK_TIME时间之后会强制执行一次

3.在线程退出的时候会尽量将剩下的任务执行完

 

package com.su.iot.server.db.cache;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import com.su.iot.server.util.LogUtil;

/**
 * Assistant of database transaction. Matin a Queue and insert to database if
 * the task arrive MAX_TASK_COUNT
 */
public class DBTransactionTask implements Runnable
{
    private static final DBTransactionTask inst = new DBTransactionTask();
    private static final int MAX_TASK_COUNT = 3;
    private static final int FORCE_WORK_TIME = 5 * 1000; //force work time
    
    private Thread mThread = null;
    private final LinkedList<Work> mWorkQueue = new LinkedList<Work>();
    private long mLastSaveTime = 0;
    
    public static DBTransactionTask i() {
        return inst;
    }
    
    @Override
    public void run() {
        mLastSaveTime = System.currentTimeMillis();
        ArrayList<Work> workList = new ArrayList<Work>();
        while (true) {
            boolean interrupted = false;
            synchronized (mWorkQueue) {
                long waitTime = 0;
                while (true) {
                    // task enough , break
                    if (mWorkQueue.size() >= MAX_TASK_COUNT) {
                        break;
                    }
                    //force work time arrive, and works exists,  break. 
                    if ((mWorkQueue.size() > 0 && (waitTime = FORCE_WORK_TIME - (System.currentTimeMillis() - mLastSaveTime)) < 0)) {
                        break;
                    }
                    try {
                        mWorkQueue.wait(waitTime);
                    }
                    catch (InterruptedException e) {
                        LogUtil.e("interrupted!");
                        e.printStackTrace();
                        interrupted = true;
                        break;
                    }
                }
                
                workList.addAll(mWorkQueue);
                LogUtil.e("mWorkQueue clear :" + mWorkQueue.size());
                mWorkQueue.clear();
            }
            
            if (!interrupted) {
                if (workList.size() > 0) {
                    // start transtraction work!
                    startTransaction(workList);
                    int ok = 0;
                    if (ok == 0) {
                        workList.clear(); //继续下一轮的work收集
                    }
                }
                mLastSaveTime = System.currentTimeMillis();
            }
            else {
                LogUtil.d("Thread was interrupted, finishing the last tasks");
                // 如果interrupted了,则尝试将没有写入数据库的数据写进去
                if (mWorkQueue.size() > 0) {
                    try {
                        // start transtraction work!
                        startTransaction(mWorkQueue);
                    }
                    catch (Exception e) {
                        LogUtil.e("save statistic data to db error,");
                        e.printStackTrace();
                    }
                }
                
            }
        }
    }
    
    public void add(final Work work) {
        LogUtil.d("adding work " + work + " mWorkQueue size" + mWorkQueue.size());
        synchronized (mWorkQueue) {
            mWorkQueue.addLast(work);
            mWorkQueue.notify();
        }
    }
    
    public synchronized void start() {
        if (mThread != null) {
            LogUtil.d("DBTransactionTask already started!");
            return;
        }
        
        mThread = new Thread(this, "DBTransactionTask");
        //        mThread.setDaemon(true);
        mThread.start();
        LogUtil.d("DBTransactionTask start");
    }
    
    public synchronized void stop() {
        if (mThread != null) {
            mThread.interrupt();
        }
        else {
            LogUtil.d("DBTransactionTask already stopped!");
        }
        
        mThread = null;
    }
    
    public boolean startTransaction(List<Work> work) {
        LogUtil.d("startTransaction----------------------------------");
        for (int i = 0; i < work.size(); i++) {
            Work work2 = work.get(i);
            if (work2 == null) {
                LogUtil.e("work is null !!");
            }
            else {
                work2.doWork();
            }
        }
        //        try {
        //            JDBCUtil.i().beginTransaction();
        //            for (int i = 0; i < work.size(); i++) {
        //                Work work2 = work.get(i);
        //                if (work2 == null) {
        //                    LogUtil.e("work is null !!");
        //                }
        //                else {
        //                    work2.doWork();
        //                }
        //            }
        //            JDBCUtil.i().commit();
        //            JDBCUtil.i().endTransaction();
        //            return true;
        //        }
        //        catch (Exception e) {
        //            JDBCUtil.i().roolback();
        //            JDBCUtil.i().endTransaction();
        //            e.printStackTrace();
        //            
        //        }
        LogUtil.d("endTransaction----------------------------------");
        return false;
    }
    
    public abstract static class Work
    {
        private String id;
        
        public Work setId(String id) {
            this.id = id;
            return this;
        }
        
        public String getId() {
            return id;
        }
        
        public abstract void doWork();
    }
    
    public static void main(String[] args) {
        DBTransactionTask.i().start();
        
        for (int i = 0; i < 5; i++) {
            final int taskid = i;
            Work work = new Work()
            {
                
                @Override
                public void doWork() {
                    LogUtil.d("I am running " + taskid);
                    try {
                        Thread.sleep(1000);
                    }
                    catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    
                }
            };
            DBTransactionTask.i().add(work);
        }
        
    }
}

 

转载于:https://my.oschina.net/sfshine/blog/790536

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值