簡體   English   中英

循環完成的CompleteableFuture構建在私有以太坊區塊鏈中

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM