在 lambda 表达式中使用最终变量 Java

Using final variable in lambda expression Java

我有一个获取大量数据的应用程序,所以我想将数据分页成块并单独处理这些块,而不是一次处理所有数据。所以我写了一个函数,我每 n 秒调用一次来检查一个块是否完成,然后处理该块。我的问题是我无法跟踪我刚刚处理了一个块并且我应该在可用时移动到下一个块的事实。我正在按照下面的代码思考一些事情,但是我不能调用 multiplier++; 因为它抱怨它不再表现得像最终变量。我想使用乘法器之类的东西,这样一旦代码处理了一个块,它 1) 就不会再次处理同一个块,并且 2) 移动到下一个块。是否有可能做到这一点?是否有一种修饰符可以放在乘数上以帮助避免竞争条件?

int multiplier = 1;
CompletableFuture<String> completionFuture = new CompletableFuture<>();

final ScheduledFuture<?> checkFuture = executor.scheduleAtFixedRate(() -> {
    // parse json response
    String response = getJSONResponse();
    JsonObject jsonObject = ConverterUtils.parseJson(response, true)
      .getAsJsonObject();

    int pages = jsonObject.get("stats").getAsJsonObject().get("pages").getAsInt();

    // if we have a chunk of n pages records then process them with dataHandler function
    if (pages > multiplier * bucketSize) {
        dataHandler.apply(getResponsePaginated((multiplier - 1) * bucketSize, bucketSize));
        multiplier++;
    }
    if (jsonObject.has("finishedAt") && !jsonObject.get("finishedAt").isJsonNull()) {
        // we are done!
        completionFuture.complete("");
    }

}, 0, sleep, TimeUnit.SECONDS);

您可以使用 AtomicInteger。由于这是一个可变类型,您可以将它分配给一个 final 变量,同时仍然能够更改它的值。这也解决了回调之间的同步问题:

final AtomicInteger multiplier = new AtomicInteger(1);
executor.scheduleAtFixedRate(() -> {
  //...
  multiplier.incrementAndGet();
}, 0, sleep, TimeUnit.SECONDS);