[英]Java completableFuture: how to parallelize several CompletableFutures
Here my code:这是我的代码:
final int startIndex = LoaderConstants.ServeiTerritorial.DEFAULT_START_INDEX;
final long pageSize = LoaderConstants.ServeiTerritorial.DEFAULT_PAGE_SIZE;
final String tableName = LoaderConstants.ServeiTerritorial.TIPUS_VIA_TABLE_NAME;
final String ownerType = LoaderConstants.ServeiTerritorial.TIPUS_VIA_OWNER_TYPE;
LongStream
.iterate(1, n -> n <= 1000 / pageSize, n -> n+1)
.mapToObj(pageNumber -> this.buildCompletableFutureOfResultSetType(tableName, ownerType, pageNumber * pageSize, pageSize))
.map(CompletableFuture::join)
What I'm trying to get is to parallelize each item.我想要得到的是并行化每个项目。
First of all, for each page, I build a CompletableFuture
:首先,对于每个页面,我构建一个CompletableFuture
:
/**
* Builds a {@link CompletableFuture} in order to get oid.
*/
private CompletableFuture<ResultSetType> buildCompletableFutureOfResultSetType(
final String tableName,
final String owner,
final long pageNumber,
final long pageSize
) {
Supplier<ResultSetType> supplier = () -> this.serveiTerritorialCatalegsClientRepository.getCataleg(tableName, null, owner, null, null, null, pageNumber, pageSize);
return CompletableFuture.supplyAsync(supplier, this.servidorTerminologicExecutor);
}
I thought it was working fine, when I've realized that it's performed sequentially.当我意识到它是按顺序执行时,我认为它运行良好。 Those are my logs:这些是我的日志:
2021-07-21 12:46:35.894 DEBUG [hes-mpi-imdg-loader,9ffb4627802548bf,9ffb4627802548bf,false] 22536 --- [ool-1-thread-38] ServeiTerritorialOidClientRepositoryImpl : Preparant crida a servei-territorial.getOid (oid: 2.16.724.4.402)
2021-07-21 12:46:35.895 DEBUG [hes-mpi-imdg-loader,9ffb4627802548bf,9ffb4627802548bf,false] 22536 --- [ool-1-thread-38] ServeiTerritorialOidClientRepositoryImpl : Creant petició cap a servei-territorial (request: <request><oid>2.16.724.4.402</oid><startIndex>13801</startIndex><pageSize>100</pageSize></request>)
2021-07-21 12:46:35.896 DEBUG [hes-mpi-imdg-loader,9ffb4627802548bf,9ffb4627802548bf,false] 22536 --- [ool-1-thread-38] ServeiTerritorialOidClientRepositoryImpl : Enviant petició a servei-territorial (request: <request><oid>2.16.724.4.402</oid><startIndex>13801</startIndex><pageSize>100</pageSize></request>)
2021-07-21 12:46:35.985 DEBUG [hes-mpi-imdg-loader,501c638f07534a0d,501c638f07534a0d,false] 22536 --- [ool-1-thread-39] ServeiTerritorialOidClientRepositoryImpl : Preparant crida a servei-territorial.getOid (oid: 2.16.724.4.402)
2021-07-21 12:46:35.986 DEBUG [hes-mpi-imdg-loader,501c638f07534a0d,501c638f07534a0d,false] 22536 --- [ool-1-thread-39] ServeiTerritorialOidClientRepositoryImpl : Creant petició cap a servei-territorial (request: <request><oid>2.16.724.4.402</oid><startIndex>13901</startIndex><pageSize>100</pageSize></request>)
2021-07-21 12:46:35.987 DEBUG [hes-mpi-imdg-loader,501c638f07534a0d,501c638f07534a0d,false] 22536 --- [ool-1-thread-39] ServeiTerritorialOidClientRepositoryImpl : Enviant petició a servei-territorial (request: <request><oid>2.16.724.4.402</oid><startIndex>13901</startIndex><pageSize>100</pageSize></request>)
2021-07-21 12:46:36.057 DEBUG [hes-mpi-imdg-loader,d840cc01f137b810,d840cc01f137b810,false] 22536 --- [ool-1-thread-40] ServeiTerritorialOidClientRepositoryImpl : Preparant crida a servei-territorial.getOid (oid: 2.16.724.4.402)
2021-07-21 12:46:36.058 DEBUG [hes-mpi-imdg-loader,d840cc01f137b810,d840cc01f137b810,false] 22536 --- [ool-1-thread-40] ServeiTerritorialOidClientRepositoryImpl : Creant petició cap a servei-territorial (request: <request><oid>2.16.724.4.402</oid><startIndex>14001</startIndex><pageSize>100</pageSize></request>)
2021-07-21 12:46:36.061 DEBUG [hes-mpi-imdg-loader,d840cc01f137b810,d840cc01f137b810,false] 22536 --- [ool-1-thread-40] ServeiTerritorialOidClientRepositoryImpl : Enviant petició a servei-territorial (request: <request><oid>2.16.724.4.402</oid><startIndex>14001</startIndex><pageSize>100</pageSize></request>)
2021-07-21 12:46:36.141 DEBUG [hes-mpi-imdg-loader,9ec5d6687eb6e9aa,9ec5d6687eb6e9aa,false] 22536 --- [ool-1-thread-41] ServeiTerritorialOidClientRepositoryImpl : Preparant crida a servei-territorial.getOid (oid: 2.16.724.4.402)
2021-07-21 12:46:36.142 DEBUG [hes-mpi-imdg-loader,9ec5d6687eb6e9aa,9ec5d6687eb6e9aa,false] 22536 --- [ool-1-thread-41] ServeiTerritorialOidClientRepositoryImpl : Creant petició cap a servei-territorial (request: <request><oid>2.16.724.4.402</oid><startIndex>14101</startIndex><pageSize>100</pageSize></request>)
2021-07-21 12:46:36.142 DEBUG [hes-mpi-imdg-loader,9ec5d6687eb6e9aa,9ec5d6687eb6e9aa,false] 22536 --- [ool-1-thread-41] ServeiTerritorialOidClientRepositoryImpl : Enviant petició a servei-territorial (request: <request><oid>2.16.724.4.402</oid><startIndex>14101</startIndex><pageSize>100</pageSize></request>)
I don't quite figure out what I'm doing wrong.我不太明白我做错了什么。
Any ideas?有任何想法吗?
You're running this sequential stream with a CompletableFutre.join
call in an intermediate step.您在中间步骤中使用CompletableFutre.join
调用运行此顺序流。
The problem is: elements traverse the (sequential) stream one at a time, and go through each step.问题是:元素一次一个地遍历(顺序)流,并遍历每一步。 This, of course, includes the join()
call.这当然包括join()
调用。 That means that for each element, the entire operation (including the "async" part, this.serveiTerritorialCatalegsClientRepository.getCataleg
) has to complete before the following element enters processing.这意味着对于每个元素,整个操作(包括“异步”部分this.serveiTerritorialCatalegsClientRepository.getCataleg
)必须在下一个元素进入处理之前完成。
To solve this, force your pipeline to create futures for all elements before join()
calls start being invoked.要解决此问题,请强制您的管道在开始调用join()
调用之前为所有元素创建期货。 Something like this should work:这样的事情应该工作:
List<CompletableFuture<ResultSetType>> submittedTasks = LongStream
.iterate(1, n -> n <= 1000 / pageSize, n -> n+1)
.mapToObj(pageNumber -> this.buildCompletableFutureOfResultSetType(tableName,
ownerType, pageNumber * pageSize,
pageSize))
.collect(Collectors.toList());
That way, the terminal collect()
will gather all submitted CompletableFuture
objects without blocking.这样,终端collect()
将无阻塞地收集所有提交的CompletableFuture
对象。 You don't need to collect to a list, but any terminal operation that is going to force the asynchronous tasks to be submitted should do;您不需要收集到列表,但任何将强制提交异步任务的终端操作都应该这样做; as long as you can manage to call join
on each task separately.只要您可以设法分别对每个任务调用join
。
After that, you can block, knowing that all asynchronous tasks have been started or at least queued.之后,您可以阻塞,知道所有异步任务都已启动或至少已排队。
submittedTasks.stream()
.map(CompletableFuture::join)
.forEach(...) //some terminal operation
This way, you avoid unnecessary blocking code.这样,您可以避免不必要的阻塞代码。
I notice that I mentioned "sequential" a few times, but that's not to imply that running the same code on a parallel stream will solve it.我注意到我多次提到“顺序”,但这并不意味着在并行流上运行相同的代码会解决它。 The main problem will persist, although throughput may improve because you'd be blocking in parallel主要问题仍然存在,尽管吞吐量可能会提高,因为您会并行阻塞
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.