基於Flux的動態批量運行任務(異步版)

相關文章

基於Flux的動態批量運行任務(阻塞版)
基於Flux的動態批量運行任務(異步版)

應用場景

事先不確定數據的數目,但是需要併發分批處理數據(比如,查詢數據庫時,可邊讀取數據,邊異步分批處理數據)。故實現基於Flux的動態批量運行任務。

調度器:決定任務在多線程、單線程還是當前線程執行。

代碼實現

Maven引用Flux

        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-core</artifactId>
            <version>3.3.0.RELEASE</version>
        </dependency>

import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import reactor.core.scheduler.Schedulers;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;
import java.util.function.Consumer;

/**
 * 基於Flux的動態批量運行器(異步版)
 *
 * @param <T> the type parameter
 */
public class FluxBatchRunner<T> {
    private Scheduler scheduler;
    private int batchSize;
    private Consumer<Collection<T>> consumer;
    private Collection<T> records;

    public FluxBatchRunner(int batchSize, Consumer<Collection<T>> consumer) {
        if (batchSize <= 0) {
            throw new IllegalArgumentException();
        }
        Objects.requireNonNull(consumer);
        this.batchSize = batchSize;
        this.consumer = consumer;
        scheduler = Schedulers.parallel();
        records = new ArrayList<>();
    }

    public FluxBatchRunner<T> setBatchSize(int batchSize) {
        this.batchSize = batchSize;
        return this;
    }

    public FluxBatchRunner<T> setScheduler(Scheduler scheduler) {
        this.scheduler = scheduler;
        return this;
    }

    /**
     * 添加數據
     *
     * @param t the t
     */
    public void add(T t) {
        records.add(t);
        if (records.size() == batchSize) {
            // copy
            subscribeToMono(new ArrayList<>(records));
            records.clear();
        }
    }

    /**
     * Do final.
     */
    public void doFinal() {
        if (!records.isEmpty()) {
            subscribeToMono(this.records);
        }
    }

    private void subscribeToMono(Collection<T> records) {
        Mono.just(records).subscribeOn(scheduler).subscribe(data -> consumer.accept(data));
    }
}

使用示例

public class FluxBatchRunnerTest {

    @Test
    public void doFinal() throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(5);
        FluxBatchRunner<Integer> batchRunner = new FluxBatchRunner<>(20, data -> {
            System.out.printf("begin:: thread=%s; size=%s%n", Thread.currentThread().getName(), data.size());
            try {
                Thread.sleep(200);
                countDownLatch.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.printf("end:: thread=%s; size=%s%n", Thread.currentThread().getName(), data.size());
        });
        IntStream.range(0, 100).forEach(batchRunner::add);
        batchRunner.doFinal();
        countDownLatch.await();
    }
}

結果

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章