簡體   English   中英

如何在Spring Boot應用程序中正確使用ThreadPoolExecutor

[英]How to work correctly with ThreadPoolExecutor in Spring Boot Application

我有一個Spring Boot Application

我的應用程序使用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寫入執行的網址:

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將插入URLexecutedUrls線程安全CopyOnWriteArrayList ,如果它成功地調用。


請記住,當不再需要ExecutorService 必須將其關閉。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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