简体   繁体   中英

How to get the queue size of the executor in real time

Supposed i have this application.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. I think we can get the value from 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. The internal implementation of size() in LinkedBlockingQueue (which ThreadPoolExecutor uses) is 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.


So the root goal is to monitor the queue, and send an alert when queue is 80% full. This should not go into your code which is responsible for making sure that your business logic works. 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. Considering that the executor can be easily injected to a separate Controller , it won't even mess up your "real" code.

As ThreadPoolTaskExecutor does not expose any API you can get the queue used by it. However, you are free to extend ThreadPoolTaskExecutor and create a CustomThreadPoolTaskExecutor override the 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:

@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.

I don't know from where you have got ThreadPoolTaskExecutor class type of executor. But in java you can typecast to ThreadPoolExecutor and get queue and it's size as below:

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.

You can then provide your queue to Spring's ThreadPoolTaskExecutor like this:

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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