我有一个大约1米记录的大表,我想对所有记录进行一些处理,所以1线程方式,就是说,1000个记录,处理它们,获得另外1000条记录等... 但是如果我想使用多任务处理呢?这是2个线程,每个获取1000条记录并行并行处理,我如何确保每个线程将获取不同的1000条记录? 注意:我正在使用hibernate
看起来像那样
public void run() {
partList=getKParts(10);
operateOnList(partList);
}
答案 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)
如果数据库中的记录确实具有类型为int
或long
的主键,请为每个线程添加限制以仅从范围中获取记录:
Thread1: 0000 - 0999, 2000 - 2999, etc
Thread2: 1000 - 1999, 3000 - 3999, etc
这样,每个帖子只需要offset
,counter
和increment
。例如,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;
}
}