相關文章
基於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();
}
}