两个线程查询表

时间:2014-04-10 08:49:22

标签: java multithreading hibernate

我有一个大约1米记录的大表,我想对所有记录进行一些处理,所以1线程方式,就是说,1000个记录,处理它们,获得另外1000条记录等... 但是如果我想使用多任务处理呢?这是2个线程,每个获取1000条记录并行并行处理,我如何确保每个线程将获取不同的1000条记录? 注意:我正在使用hibernate

看起来像那样

public void run() {


    partList=getKParts(10);
    operateOnList(partList);


}

4 个答案:

答案 0 :(得分:2)

当然,您可以同步代码。

public class MyClass {

    private final HibernateFetcher hibernateFetcher = new HibernateFetcher();

    private class Worker implements Runnable {    
       public run() {    
         List partList = hibernateFetcher.fetchRecords();
         operateOnList(partList);    
       }
    }

    public void myBatchProcessor() {

      while(!hibernateFetcher.isFinished()) {
      // create *n* workers and go!

      }    
   }       
}

class HibernateFetcher {        

  private int count = 0; 
  private final Object lock = new Object();
  private volatile boolean isFinished = false;  
  public List fetchRecords() {

      Criteria criteria = ...;

      synchronized(lock) {
         criteria.setFirstResult(count) // offset
                 .setMaxResults(1000);
         count=count+1000;
      }
      List result = criteria.list();
      isFinished = result.length > 0 ? false: true;
      return result;
  }

  public synchronized boolean isFinished(){
    return isFinished;
  }

}

答案 1 :(得分:1)

如果我理解正确,你不希望提前获取1m记录,但是希望它以1000的批量获得,然后在2个线程中处理它们但是使它并行。 首先,您必须使用RowCount或其他东西在数据库查询中实现分页类型功能。从Java可以将fromRowCount传递给toRowCount并以1000个批次获取记录并在线程中并行处理它们。我在这里添加示例代码,但您必须进一步为不同的变量实现逻辑。

        int totalRecordCount = 100000;
        int batchSize =1000;
        ExecutorService executor = Executors.newFixedThreadPool(totalRecordCount/batchSize);
        for(int x=0; x < totalRecordCount;){
            int toRowCount = x+batchSize;
            partList=getKParts(10,x,toRowCount);
            x= toRowCount + 1;
            executor.submit(new Runnable<>() {
                @Override
                public void run() {
                    operateOnList(partList);
                }
            });
        }

希望这会有所帮助。如果需要进一步澄清,请告诉我

答案 2 :(得分:0)

如果数据库中的记录确实具有类型为intlong的主键,请为每个线程添加限制以仅从范围中获取记录:

Thread1: 0000 - 0999, 2000 - 2999, etc
Thread2: 1000 - 1999, 3000 - 3999, etc

这样,每个帖子只需要offsetcounterincrement。例如,Thread1的偏移量为0,而Thread2的偏移量为1000.由于此示例中有两个线程,因此增量为2000.对于每一轮增量计数器(从0)每个线程并计算下一个范围:

form = offset +(count * 2000)    to = from + 999

答案 3 :(得分:0)

import com.se.sas.persistance.utils.HibernateUtils;

public class FinderWorker implements Runnable {


    @Override
    public void run() {
        operateOnList(getNParts(IndexLocker.getAllowedListSize()));

    }

    public List<Parts> getNParts(int listSize) {

        try {

            criteria = .....
            // *********** SYNCHRONIZATION OCCURS HERE ********************//
            criteria.setFirstResult(IndexLocker.getAvailableIndex());
            criteria.setMaxResults(listSize);
            partList = criteria.list();

        } catch (Exception e) {
            e.printStackTrace();

        } finally {

            session.close();
        }
        return partList;
    }

    public void operateOnList(List<Parts> partList) {
    ....
    }

}

更衣室类

public class IndexLocker {

    private static AtomicInteger index = new AtomicInteger(0);

    private final static int batchSize = 1000;

    public IndexLocker() {

    }

    public static int getAllowedListSize() {
        return batchSize;

    }

    public static synchronized void incrmntIndex(int hop) {
        index.getAndAdd(hop);
    }

    public static synchronized int getAvailableIndex() {

        int result = index.get();
        index.getAndAdd(batchSize);
        return result;
    }

}