简体   繁体   English

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

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

Supposed i have this application.java假设我有这个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;
    }
}

My goal is to create an alert if the current real time queue size of the async executor is in 80% or nearly the limit.我的目标是在异步执行器的当前实时队列大小在 80% 或接近限制时创建警报。 I think we can get the value from executor.getThreadPoolExecutor().getQueue().size();我认为我们可以从executor.getThreadPoolExecutor().getQueue().size(); . . Im currently stuck on how to achieve that我目前坚持如何实现这一目标

@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();
    }
}

If you can provide the bean as a ThreadPoolExecutor , then you don't even need the cast.如果您可以将 bean 作为ThreadPoolExecutor提供,那么您甚至不需要演员表。 The internal implementation of size() in LinkedBlockingQueue (which ThreadPoolExecutor uses) is AtomicInteger.get() . LinkedBlockingQueue (ThreadPoolExecutor 使用)中size()的内部实现是AtomicInteger.get()

So there's no need to get creative and build your own mechanisms, it's all built-in.所以没有必要发挥创造力并建立自己的机制,这一切都是内置的。 Based on Spring 4.2, but shouldn't depend on the version too much.基于 Spring 4.2,但不应过多依赖版本。


So the root goal is to monitor the queue, and send an alert when queue is 80% full.所以根本目标是监控队列,并在队列满 80% 时发送警报。 This should not go into your code which is responsible for making sure that your business logic works.这不应该 go 到您负责确保您的业务逻辑正常工作的代码中。 You shouldn't make hacks there to account for lack of resources.你不应该因为缺乏资源而在那里进行黑客攻击。 If the idea is that you should throttle users when the queue is packed, there are far better ways to handle those.如果你的想法是当队列被挤满时你应该限制用户,那么有更好的方法来处理这些。

Since the idea is to do "light monitoring", ie there's no attempt to handle a case when queue is 80% full, a polling solution would be lightweight enough.由于这个想法是做“轻量级监控”,即当队列已满 80% 时不会尝试处理情况,因此轮询解决方案将足够轻量级。 Considering that the executor can be easily injected to a separate Controller , it won't even mess up your "real" code.考虑到执行器可以很容易地注入到单独的Controller中,它甚至不会弄乱你的“真实”代码。

As ThreadPoolTaskExecutor does not expose any API you can get the queue used by it.由于ThreadPoolTaskExecutor Executor 没有公开任何 API 你可以得到它使用的队列。 However, you are free to extend ThreadPoolTaskExecutor and create a CustomThreadPoolTaskExecutor override the createQueue .但是,您可以自由扩展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;
    }
}

Now you can create asyncExecutor like below:现在您可以像下面这样创建asyncExecutor

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

Your CustomThreadPoolTaskExecutor executor has public method getQueue and you can use that to get the queue.您的CustomThreadPoolTaskExecutor执行程序具有公共方法getQueue ,您可以使用它来获取队列。

I don't know from where you have got ThreadPoolTaskExecutor class type of executor.我不知道你从哪里得到ThreadPoolTaskExecutor Executor class 类型的执行器。 But in java you can typecast to ThreadPoolExecutor and get queue and it's size as below:但在 java 中,您可以类型转换为ThreadPoolExecutor并获取队列,其大小如下:

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

To do this in real-time as you're asking for is not so easy.按照您的要求实时执行此操作并不容易。 You'll need to decorate the methods of BlockingQueue so that you can add code to execute immediately when the content of the queue changes.您需要装饰BlockingQueue的方法,以便您可以添加代码以在队列内容更改时立即执行。

You can then provide your queue to Spring's ThreadPoolTaskExecutor like this:然后,您可以像这样将队列提供给 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