【问题标题】:Run limited number of threads on Spring Boot service在 Spring Boot 服务上运行有限数量的线程
【发布时间】:2016-11-23 08:46:14
【问题描述】:

我目前正在使用 Spring Boot 开发一个 Web 应用程序,但我在服务层遇到了问题。

我的服务层有一个繁重的方法。如果多个用户调用相同的服务,应用程序会因内存不足而停止。所以我只想限制该方法的并行运行线程的数量。到目前为止,我已经在该方法上使用了 synchronized。但它会将其限制为单线程方法。

@Service
public class DocumentService{

    private synchronized void doReplacement(){
       //should have limited no of multi threads (eg. 3)
    }

    private void normalMethod(){
       //no restrictions
    }

}

我能做些什么来完成这项任务。任何帮助将不胜感激。

【问题讨论】:

  • 在执行时对方法应用手动锁定,如果没有......也许thisthis可能会有所帮助......
  • 你可以创建和使用 Executor 来限制线程数。 BTW 先检查有没有内存泄漏......
  • 由于spring框架在服务层创建了所有线程,我无法手动处理线程。有办法吗??
  • 解决此问题的常用方法是将您的服务包装在服务提供者中。提供者使用计数信号量来确保不超过 X 个事物的实例存在,并阻止请求它的线程。另一种选择是更改 tomcat 配置(如果您在内部使用 tomcat)以限制它将为每个请求处理的并发线程数,但这可能会对您的应用程序的其余部分产生连锁反应。
  • @christopher 可以举个例子吗?

标签: java spring multithreading spring-mvc spring-boot


【解决方案1】:

使用某种请求限制(即每秒的请求数)可能比使用可以同时执行方法的线程数更好。例如直接使用Guava's RateLimiter,或者事件adding declarative support for with Spring's AOP

如果您仍想使用线程,我的建议是使用 ExecutorService:

@Service
public class DocumentService {

    private final ExecutorService executor;

    @Autowired
    public DocumentService(
        @Value("${some.config.property}") int maxConcurrentThreads) {
        // will allow only the given number of threads
        executor = Executors.newFixedThreadPool(maxConcurrentThreads);
    }

    private void doReplacementWithLimitedConcurrency(String s, int i){
        Future<?> future = executor.submit(() -> doReplacement(s, i));
        future.get(); // will block until a thread picks up the task
                      // and finishes executing doReplacement
    }

    private void doReplacement(String s, int i){
    }

    // other methods

    @PreDestroy
    public void performThreadPoolCleanup() throws Exception {
        executor.shutdown();
        executor.awaitTermination(10, TimeUnit.SECONDS); 
        executor.shutdownNow();
    }
}

【讨论】:

  • 这里的问题是我必须在 doReplacement 中传递一些参数,例如 doReplacement(String s,Int i)。提交中的 Callable 不允许参数。我该如何解决这个问题?
  • 感谢 Milos,我创建了一个作为 DoReplacement 的类并由 Callable 实现。并使用构造函数将值传递给它。
  • 这也行得通,尽管它比使用 lambda 效率要低一些。除非您仍在使用 Java 7,否则这很有意义:)
  • 哇 lambda 来救援了。有用。你能解释一下你在那里做了什么吗?我不熟悉 () -> 你在那里使用的标志。我知道它是 lambda。但是 submit 要求 Callable 并且您在那里使用了 lambda 表达式。怎么样?
  • Java 8 允许您使用 lambda 表达式表示功能接口(包含单个抽象方法的接口),其中 lambda 基本上是该接口方法的简写定义。在这种情况下,submit 也接受一个 Runnable 并且 Runnable 是一个函数式接口,因此 Java 会将 () -&gt; doReplacement(s, i) 解释为 Runnable 的实现。我建议你听this fantastic talk by Venkat Subramaniam
猜你喜欢
  • 2017-07-16
  • 2019-08-06
  • 2019-03-27
  • 2017-07-17
  • 2019-02-13
  • 2021-08-20
  • 1970-01-01
  • 1970-01-01
  • 2023-01-25
相关资源
最近更新 更多