Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 生产者和消费者分批生产;第二批';直到上一批货完成,我才来_Java_Multithreading_Batch Processing_Producer Consumer - Fatal编程技术网

Java 生产者和消费者分批生产;第二批';直到上一批货完成,我才来

Java 生产者和消费者分批生产;第二批';直到上一批货完成,我才来,java,multithreading,batch-processing,producer-consumer,Java,Multithreading,Batch Processing,Producer Consumer,我试图实现一种机制,其中可运行者既是生产者又是消费者 情况是- 我需要从数据库中批量读取记录,并对其进行处理。我正在尝试使用生产者-消费者模式。我得到一批,我处理。获取批处理、进程。每当它看到队列为空时,就会得到一个批处理。其中一条线去拿东西。但问题是,我无法标记获取用于处理的记录,这是我的限制。因此,如果我们在完全提交前一批之前获取下一批,我可能会再次获取相同的记录。因此,我需要能够在拉动另一个之前完全提交前一个。我不知道在这里该怎么办。我试着保持已获取的一个的计数,然后保持我的get,直到达

我试图实现一种机制,其中可运行者既是生产者又是消费者

情况是-

我需要从数据库中批量读取记录,并对其进行处理。我正在尝试使用生产者-消费者模式。我得到一批,我处理。获取批处理、进程。每当它看到队列为空时,就会得到一个批处理。其中一条线去拿东西。但问题是,我无法标记获取用于处理的记录,这是我的限制。因此,如果我们在完全提交前一批之前获取下一批,我可能会再次获取相同的记录。因此,我需要能够在拉动另一个之前完全提交前一个。我不知道在这里该怎么办。我试着保持已获取的一个的计数,然后保持我的get,直到达到该计数

处理这种情况的最好方法是什么?以块的形式处理数据库中的记录——我在这里遇到的最大限制是,我无法标记已拾取的记录。所以,我想按顺序进行批处理。但是批处理应该在内部使用多线程

public class DealStoreEnricher extends AsyncExecutionSupport {
private static final int BATCH_SIZE = 5000;
private static final Log log = LogFactory.getLog(DealStoreEnricher.class);
private final DealEnricher dealEnricher;
private int concurrency = 10;
private final BlockingQueue<QueryDealRecord> dealsToBeEnrichedQueue;
private final BlockingQueue<QueryDealRecord> dealsEnrichedQueue;
private DealStore dealStore;
private ExtractorProcess extractorProcess;
ExecutorService executor;

public DealStoreEnricher(DealEnricher dealEnricher, DealStore dealStore, ExtractorProcess extractorProcess) {
    this.dealEnricher = dealEnricher;
    this.dealStore = dealStore;
    this.extractorProcess = extractorProcess;
    dealsToBeEnrichedQueue = new LinkedBlockingQueue<QueryDealRecord>();
    dealsEnrichedQueue = new LinkedBlockingQueue<QueryDealRecord>(BATCH_SIZE * 3);
}

public ExtractorProcess getExtractorProcess() {
    return extractorProcess;
}

public DealEnricher getDealEnricher() {
    return dealEnricher;
}

public int getConcurrency() {
    return concurrency;
}

public void setConcurrency(int concurrency) {
    this.concurrency = concurrency;
}

public DealStore getDealStore() {
    return dealStore;
}

public DealStoreEnricher withConcurrency(int concurrency) {
    setConcurrency(concurrency);
    return this;
}

@Override
public void start() {
    super.start();
    executor = Executors.newFixedThreadPool(getConcurrency());
    for (int i = 0; i < getConcurrency(); i++)
        executor.submit(new Runnable() {
            public void run() {
                try {
                    QueryDealRecord record = null;
                    while ((record = get()) != null && !isCancelled()) {
                        try {
                            update(getDealEnricher().enrich(record));
                            processed.incrementAndGet();
                        } catch (Exception e) {
                            failures.incrementAndGet();
                            log.error("Failed to process deal: " + record.getTradeId(), e);
                        }
                    }
                } catch (InterruptedException e) {
                    setCancelled();
                }
            }
        });

    executor.shutdown();
}

protected void update(QueryDealRecord enrichedRecord) {
    dealsEnrichedQueue.add(enrichedRecord);
    if (batchComplete()) {
        List<QueryDealRecord> enrichedRecordsBatch = new ArrayList<QueryDealRecord>();
        synchronized (this) {
            dealsEnrichedQueue.drainTo(enrichedRecordsBatch);
        }
        if (!enrichedRecordsBatch.isEmpty())
            updateTheDatabase(enrichedRecordsBatch);
    }
}

private void updateTheDatabase(List<QueryDealRecord> enrichedRecordsBatch) {
    getDealStore().insertEnrichedData(enrichedRecordsBatch, getExtractorProcess());
}

/**
 * @return true if processed records have reached the batch size or there's
 *         nothing to be processed now.
 */
private boolean batchComplete() {
    return dealsEnrichedQueue.size() >= BATCH_SIZE || dealsToBeEnrichedQueue.isEmpty();
}

/**
 * Gets an item from the queue of things to be enriched
 * 
 * @return {@linkplain QueryDealRecord} to be enriched
 * @throws InterruptedException
 */
protected synchronized QueryDealRecord get() throws InterruptedException {
    try {
        if (!dealsToBeEnrichedQueue.isEmpty()) {
            return dealsToBeEnrichedQueue.take();
        } else {
            List<QueryDealRecord> records = getNextBatchToBeProcessed();
            if (!records.isEmpty()) {
                dealsToBeEnrichedQueue.addAll(records);
                return dealsToBeEnrichedQueue.take();
            }
        }
    } catch (InterruptedException ie) {
        throw new UnRecoverableException("Unable to retrieve QueryDealRecord", ie);
    }
    return null;
}

private List<QueryDealRecord> getNextBatchToBeProcessed() {


    List<QueryDealRecord> recordsThatNeedEnriching = getDealStore().getTheRecordsThatNeedEnriching(getExtractorProcess());

    return recordsThatNeedEnriching;
}

@Override
public void stop() {
    super.stop();
    if (executor != null)
        executor.shutdownNow();
}

@Override
public boolean await() throws InterruptedException {
    return executor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS) && !isCancelled() && complete();
}

@Override
public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
    return executor.awaitTermination(timeout, unit) && !isCancelled() && complete();
}

private boolean complete() {
    setCompleted();
    return true;
}
公共类DealStoreEnricher扩展了AsyncExecutionSupport{
专用静态最终整数批大小=5000;
私有静态最终日志日志=LogFactory.getLog(DealStoreEnricher.class);
私人最终DealEnricher DealEnricher;
私有int并发=10;
私有最终阻塞队列dealsToBeEnrichedQueue;
私有最终阻塞队列dealsEnrichedQueue;
私人交易商店;
私有提取器进程提取器进程;
执行人服务执行人;
公共DealStoreEnricher(DealEnricher DealEnricher,DealStore DealStore,提取器进程提取器进程){
this.dealEnricher=dealEnricher;
this.dealStore=dealStore;
this.extractorProcess=extractorProcess;
dealsToBeEnrichedQueue=新建LinkedBlockingQueue();
dealsEnrichedQueue=新的LinkedBlockingQueue(批量大小*3);
}
公共提取器进程getExtractor进程(){
返回提取器进程;
}
公共DealEnricher getDealEnricher(){
返回式脱包器;
}
公共int getConcurrency(){
返回并发;
}
公共void setConcurrency(int concurrency){
this.concurrency=并发;
}
公共DealStore getDealStore(){
退货商店;
}
具有并发性的公共DealStoreEnricher(int并发性){
setConcurrency(并发);
归还这个;
}
@凌驾
公开作废开始(){
super.start();
executor=Executors.newFixedThreadPool(getConcurrency());
for(int i=0;i=BATCH_size | | dealsToBeEnrichedQueue.isEmpty();
}
/**
*从要充实的内容队列中获取项目
* 
*@return{@linkplain QueryDealRecord}将被充实
*@抛出中断异常
*/
受保护的同步QueryDealRecord get()引发InterruptedException{
试一试{
如果(!dealsToBeEnrichedQueue.isEmpty()){
return dealsToBeEnrichedQueue.take();
}否则{
列表记录=getNextBatchToBeProcessed();
如果(!records.isEmpty()){
dealsToBeEnrichedQueue.addAll(记录);
return dealsToBeEnrichedQueue.take();
}
}
}捕获(中断异常ie){
抛出新的不可恢复异常(“无法检索QueryDealRecord”,即);
}
返回null;
}
私有列表getNextBatchToBeProcessed(){
List RecordsThatNeedFurning=getDealStore().GetTheRecordsThatNeedFurning(getExtractorProcess());
返回所需的记录;
}
@凌驾
公共停车场(){
super.stop();
if(executor!=null)
执行者。关机现在();
}
@凌驾
public boolean await()抛出InterruptedException{
返回executor.awaitTermination(Long.MAX_值,TimeUnit.SECONDS)和&!isCancelled()和&complete();
}
@凌驾
公共布尔等待(长超时,时间单位)抛出InterruptedException{
返回执行器。等待终止(超时,单位)&&!isCancelled()&&complete();
}
私有布尔完成(){
setCompleted();
返回true;
}
}

您已经在使用a-它可以为您完成所有工作

但是,您使用了错误的方法
addAll()
将新元素添加到队列中。如果队列不能接受元素,该方法将抛出异常。相反,您应该使用
put()
,因为这是阻塞方法
BlockingQueue blockingQueue = ...;
Semapore semaphore = new Semaphore(1);
Batch batch = db.getBatch();
semaphore.acquire(); // wait until previous batch completes
blockingQueue.add(batch);
for(;;){
    Batch batch = blockingQueue.take();
    doBatchUpdate(batch);
    semaphore.release(); // tell next batch to run
}