关于多线程处理数据并发问题处理

来源:互联网 发布:长者是谁 知乎 编辑:程序博客网 时间:2024/05/09 07:16

数据量多时需要要多线程处理,尤其在集群环境下很可能发生资源竞争的情况,此时就需要谨慎的对数据加锁,如果加锁出了问题,也是个麻烦事。

为安全考虑,一般处理这种问题有几个步骤:

为此个业务加开关,如果出现问题,将开关关闭。但是遇到一些紧急问题,开关关闭会影响业务,这时就需要走以下逻辑:

1、数据量多,则数据取出后用线程池分批处理数据。

2、数据量不多,单线程就可以处理;建议建一个线程表专门处理线程锁问题。这里我们建一个asgin_thread的线程表,表中的字段有id,SYNSTATE,VERSION,其中SYNSTATE为同步状态,VERSION为版本号;其中的id是自己定义的,加锁时也只加锁这个表中的某一条数据,不能对业务表进行加锁,将事务放到biz层,这样的话整个biz层的逻辑同在一个事务内,加锁才起作用。此处用乐观锁处理,将asgin_thread的单条数据加锁后,统一业务层的其他逻辑都完成事务提交后锁释放。以下是代码:


while (running) {
      try {
        Thread.sleep(sleepTime);
      } catch (InterruptedException e) {
        log.error("异常:", e);
      }
      List<Bean> tasklist = null;
      try {
        tasklist = asignThreadBiz.update(loadCount);
        log.info("装载已锁定数据");
      } catch (Exception e) {
        log.error("线程出现锁冲突,重新进行取数据....!",e);
        continue;
      } 
      
      if (tasklist != null && !tasklist.isEmpty()) {
        
        WorkThread<List<Bean>> ecThread = createWorkThread();
        ecThread.setTaskList(tasklist);
        threadPool.execute(ecThread);
      }
      // 状态重制
      resetStatus();
    }


处理数据流程:

  asignDao.updateCount();  //线程表单条数据加锁
    List<Bean> retlist = new ArrayList<Bean>();
    
    int retval = BeantDao.setLock(loadcount); //打标记
    if(retval > 0){
      retlist = beantDao.loadLock(); //取数据
    }


乐观锁:

AsginThread asgin = this.load(100000L);
asgin.setSynstate(asgin.getSynstate()+1);
this.saveOrUpdate(asgin);