我有一个 Spring Boot 应用程序
。
我的应用程序使用 restTemplate
向另一个应用程序发送请求。
我需要向一百个不同的应用程序(在不同的服务器上)发送请求。我使用:
publi class Service {
private RestClient restClient;
private List<String> urls;
private ThreadPoolExecutor executor;
public Service(RestClient restClient, List<String> urls, ThreadPoolExecutor executor){
this.restClient = restClient;
this.urls = urls;
this.executor = executor;
}
public void sendPost(Entity entity){
for (String url: urls){
executor.execute(() -> restClient.create(url, entity);
}
}
}
我正在尝试使用ThreadPoolExecutor(fixedSizeThreadPool)
,但我有一些问题。
1。我读到 threadPoolExecutor
是线程安全的。这是否意味着我可以从不同的线程同时调用 execute()
并且它会正常工作?
2。如果 threadPoolExecutor
中没有空闲线程,它会减慢应用程序的速度,我应该选择合理的池大小,对吗?
3。例如,我需要在ArrayList
中写入执行的url:
public void sendPost(Entity entity){
List<String> executedUrls = new ArrayList<>();
for (String url: urls){
executor.execute(() -> restClient.create(url, entity, executedUrls);
}
}
RestClient
发送请求,如果执行成功,就会添加到ArrayList
中。
如果我在 threadPool
的任何线程中出现异常,我希望 ArrayList
将包含成功执行的 url 列表。
它会按我的预期工作吗?或者我可能会遇到丢失更新之类的情况?
最佳答案
您可以使用ExecutorService
。
例如,创建一个新的 ExecutorService
(缓存的 ThreadPoolExecutor
可能更好)
private final ExecutorService executorService = Executors.newCachedThreadPool();
创建自定义Runnable
实现
static class RestRunnable implements Runnable {
private final String url;
private final RestTemplate restTemplate;
private final Collection<? super String> executedUrls;
RestRunnable(
final String url,
final RestTemplate restTemplate,
final Collection<? super String> executedUrls) {
this.url = url;
this.restTemplate = restTemplate;
this.executedUrls = executedUrls;
}
@Override
public void run() {
final ResponseEntity<?> response = restTemplate.exchange(...);
if (response.getStatusCode() == HttpStatus.OK) {
executedUrls.add(url);
}
}
}
对于每个 URL
,向 ExecutorService
提交一个新任务
final Collection<String> urls = new ArrayList<>();
final Collection<String> executedUrls = new CopyOnWriteArrayList<>();
...
for (final String url : urls) {
// The RestTemplate instance is retrieved via Spring Bean, or created manually
executorService.submit(new RestRunnable(url, restTemplate, executedUrls));
}
RestRunnable
如果调用成功,会将 URL
插入到 executedUrls
线程安全的 CopyOnWriteArrayList
中。
记住ExecutorService
必须在不再需要时关闭。
关于java - 如何在 Spring Boot 应用程序中正确使用 ThreadPoolExecutor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55269656/