如果线程池已满时我的线程睡眠时间大于保持活动秒数,会发生什么



我有一个spring-boot应用程序,用户在其中到达一个端点,我必须确认我立即收到了他们的请求。我需要在不同的线程上进行一些计算,并在计算结束后在不同的端点上向它们发送响应。对于在不同的线程上执行任务,我的线程池配置如下所示:

@Configuration
@EnableAsync
public class SpringAsyncMatchingConfig {
@Bean(name = "threadTaskExecutor") 
public TaskExecutor getMatchingTaskExecutor() {  
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();  
threadPoolTaskExecutor.setCorePoolSize(10);
threadPoolTaskExecutor.setQueueCapacity(0);
threadPoolTaskExecutor.setMaxPoolSize(15); 
return threadPoolTaskExecutor;  
}  
}

当我进行计算时,我需要到达其中一个端点,该端点会返回一个令牌id并进行一些计算。计算通常需要3到4分钟。因此,我所做的是,我提到了Thread.sleep(30000),在30秒后,我再次使用它提供的令牌id访问同一个api,希望它能给我一个结果。

while(result == false) {
Thread.sleep(30000)
result = callendpoint(tokenid)
}

假设我的线程池用完了,它达到了15个线程的最大大小,并且向池中提供了更多的任务,我的一些线程将处于30秒睡眠状态,这些线程会因为我处于睡眠(空闲(状态而被终止并分配新任务吗?我应该添加"保持活动"集以防止这种情况发生吗?

threadPoolTaskExecutor.setKeepAliveSeconds(120); 

这样做对吗?

假设我的线程已经耗尽,它达到了最大大小15,并且向线程提供了更多的任务,我的一些线程将处于30秒睡眠状态

这是可能发生的。这样的队列是使用LinkedBlockingQueue实现的,其行为如下(源Spring Framework 5.3.X参考文档:7.4.2。executor元素(:

  1. 如果达到queueCapacity,则执行器将创建一个新线程,该线程位于corePoolSize之外,直至maxPoolSize
  2. 如果queueCapacity也达到maxPoolSize线程数,则任务被拒绝

默认容量是无限的(实际上是Integer.MAX_VALUE(,这意味着将只分配corePoolSize数量的线程。如果要使队列容量间隔,请记住将maxPoolSize设置为比corePoolSize高一点。为了确保不会拒绝任何任务,您必须找到coremax线程数量的适当平衡。当然,所有这些数字在很大程度上取决于预期吞吐量。用一个";"无限";队列容量,您不需要担心,但是,性能调优也有点有限。


threadPoolTaskExecutor.setKeepAliveSeconds(120);

这样做对吗?

我不这么认为。说到上面的片段,请注意,Thread.sleep(30000)这么长的时间并不能帮助您进行有效的结果轮询,而可以通过CompletableFuture进行处理。当5分钟后结果不可用时,使用CompletableFuture::get(long timeout, TimeUnit unit)停止线程。看看下面你能做什么:

@Component
public class AsyncClient {
@Async
public CompletableFuture<Result> fetchResult(String tokenId) {
Result result = callEndpoint(tokenId);                      // a long call
return CompletableFuture.completedFuture(results);
}
}
@Service
public class TokenService {
private final AsyncClient asyncClient;
public Result callEndpoint(String tokenId) 
throws InterruptedException, ExecutionException, TimeoutException 
{
CompletableFuture<Result> completableFuture = asyncClient.fetchResult(tokenId);
return completableFuture.get(5, TimeUnit.SECONDS);
}
}

最后,让我提醒您使用@Async的三个基本规则:

  • 它只能应用于public方法
  • 它不能从定义的同一类中调用
  • 返回类型必须是void(更适合作业(或Future

相关内容

  • 没有找到相关文章

最新更新