繁体   English   中英

如何实时获取executor的队列大小

[英]How to get the queue size of the executor in real time

假设我有这个application.java 。java

@SpringBootApplication
public class Application {
    public static void main(String[] args){
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public Executor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(50);
        executor.setMaxPoolSize(100);
        executor.setQueueCapacity(5000);
        executor.setThreadNamePrefix("sm-async-");
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.initialize();
        return executor;
    }
}

我的目标是在异步执行器的当前实时队列大小在 80% 或接近限制时创建警报。 我认为我们可以从executor.getThreadPoolExecutor().getQueue().size(); . 我目前坚持如何实现这一目标

@Controller
public class QueueMonitorController {

    @Autowired
    private Executor executor;

    @RequestMapping(value = "/queuesize", method = RequestMethod.GET)
    public int queueSize() {
        ThreadPoolExecutor tpe = (ThreadPoolExecutor)executor;
        return tpe.getQueue().size();
    }
}

如果您可以将 bean 作为ThreadPoolExecutor提供,那么您甚至不需要演员表。 LinkedBlockingQueue (ThreadPoolExecutor 使用)中size()的内部实现是AtomicInteger.get()

所以没有必要发挥创造力并建立自己的机制,这一切都是内置的。 基于 Spring 4.2,但不应过多依赖版本。


所以根本目标是监控队列,并在队列满 80% 时发送警报。 这不应该 go 到您负责确保您的业务逻辑正常工作的代码中。 你不应该因为缺乏资源而在那里进行黑客攻击。 如果你的想法是当队列被挤满时你应该限制用户,那么有更好的方法来处理这些。

由于这个想法是做“轻量级监控”,即当队列已满 80% 时不会尝试处理情况,因此轮询解决方案将足够轻量级。 考虑到执行器可以很容易地注入到单独的Controller中,它甚至不会弄乱你的“真实”代码。

由于ThreadPoolTaskExecutor Executor 没有公开任何 API 你可以得到它使用的队列。 但是,您可以自由扩展ThreadPoolTaskExecutor Executor 并创建一个CustomThreadPoolTaskExecutor覆盖createQueue

public class CustomThreadPoolTaskExecutor extends ThreadPoolTaskExecutor{

    private BlockingQueue<Runnable> queue;

    @Override
    protected BlockingQueue<Runnable> createQueue(int queueCapacity) {
        queue = super.createQueue(queueCapacity);
        return queue;
    }

    public BlockingQueue<Runnable> getQueue(){
      return queue;
    }
}

现在您可以像下面这样创建asyncExecutor

@Bean
public Executor asyncExecutor() {
    ThreadPoolTaskExecutor executor = new CustomThreadPoolTaskExecutor();
    //set other properties
    executor.initialize();
    return executor;
}

您的CustomThreadPoolTaskExecutor执行程序具有公共方法getQueue ,您可以使用它来获取队列。

我不知道你从哪里得到ThreadPoolTaskExecutor Executor class 类型的执行器。 但在 java 中,您可以类型转换为ThreadPoolExecutor并获取队列,其大小如下:

ThreadPoolExecutor executorService =  (ThreadPoolExecutor )Executors.newCachedThreadPool();
        executorService.getQueue().size()

按照您的要求实时执行此操作并不容易。 您需要装饰BlockingQueue的方法,以便您可以添加代码以在队列内容更改时立即执行。

然后,您可以像这样将队列提供给 Spring 的ThreadPoolTaskExecutor

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor() {
  @Override
  protected BlockingQueue<Runnable> createQueue(int queueCapacity) {

    // create and return your instance of blocking queue here
  }
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM