[英]CompleteableFuture in a loop contruct in a private Ethereum Blockchain
我有一個私人的以太坊區塊鏈,上面裝有5台機器。 截至目前,塊鏈的大小(塊數)為300。該處理在后端Java上完成。
我需要以異步方式運行以下循環構造。 循環的瓶頸是在執行以下命令期間:
EthBlock eb = web3.ethGetBlockByNumber(new DefaultBlockParameterNumber(BigInteger.valueOf(i)), true).send();
該命令還可以通過在此處給出的supplyAsync()
結尾結束它來返回Completablefuture<EthBlock>
對象https://github.com/web3j/web3j#start-sending-requests僅調用supplyAync().get()
消除並行性方面並使其行為同步。
public void businessLogic() throws Exception {
recentBlocks = new ArrayList<EthBlock.Block>();
for (long i = 1; i <= 300000; i++) {
EthBlock eb = web3.ethGetBlockByNumber(new DefaultBlockParameterNumber(BigInteger.valueOf(i)), true).send();
if (eb == null || eb.getBlock() == null) {
continue;
}
EthBlock.Block block = eb.getBlock();
recentBlocks.add(block);
}
}
我無法掌握將代碼轉換為CompleteableFuture可以操作的方式的機構。 目標是web.ethGetBlockNumber(...).supplyAync()
多次調用“分組”為一個集合,並一次調用它們以更新一個數組,該數組將由EthBlock
對象(即recentBlocks
。
這是我想出的:
public void businessLogic() throws Exception {
recentBlocks = new ArrayList<EthBlock.Block>();
List<CompleteableFuture> compFutures = new ArrayList<>();
for (long i = 0, i <= 300000, i++){
CompleteableFuture<EthBlock> compFuture = eb3.ethGetBlockByNumber(new DefaultBlockParameterNumber(BigInteger.valueOf(i)), true).sendAsync();
compFuture.thenAcceptAsync(eb -> // Doesn't look right
EthBlock.Block block = eb.getBlock();
recentBlock.add(block);)
compFutures.add(compFuture);
}
CompleteableFuture.allOf(compFutures).get();
}
實現IntStream
long start = System.nanoTime();
recentBlocks = IntStream.rangeClosed(0, 300_000)
.parallel()
.mapToObj(i -> {
try {
System.out.println("Current Thread -> " + Thread.currentThread());
return web3.ethGetBlockByNumber(new DefaultBlockParameterNumber(BigInteger.valueOf(i)), true).send();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
})
.filter(Objects::nonNull)
.map(EthBlock::getBlock)
.filter(Objects::nonNull)
.collect(Collectors.toList());
long stop = System.nanoTime();
System.out.println("Time Elapsed: " + TimeUnit.MICROSECONDS.convert(stop-start, TimeUnit.NANOSECONDS));
CompletableFuture包含一個get的重寫: get(long timeout, TimeUnit unit)
。 如果get超時在特定時間內沒有返回,則可以使用它進行輪詢。
假設結果List
的順序並不重要,您可能可以從並行流中受益,而不必依賴CompletableFuture
:
IntStream.rangeClosed(0, 300_000)
.parallel()
.mapToObj(i -> web3.ethGetBlockByNumber(new DefaultBlockParameterNumber(BigInteger.valueOf(i)), true).send())
.filter(Objects::nonNull)
.map(EthBlock::getBlock)
.filter(Objects::nonNull)
.collect(Collectors.toList());
因為您說那沒有幫助,所以讓我們嘗試使用緩存線程池的ExecutorService
:
List<EthBlock.Block> blocks = Collections.synchronizedList(new ArrayList<>(300_000));
ExecutorService service = Executors.newCachedThreadPool();
for (int i = 0; i <= 300_000; i++) {
BigInteger number = BigInteger.valueOf(i);
service.execute(() -> {
EthBlock eb = web3.ethGetBlockByNumber(new DefaultBlockParameterNumber(number), true).send();
if (eb == null) {
return;
}
EthBlock.Block block = eb.getBlock();
if (block != null) {
blocks.add(block);
}
});
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.