如何实时获取执行程序的队列大小

时间:2019-10-16 09:36:52

标签: java spring spring-boot asynchronous

假设我有这个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;
    }
}

我的目标是在异步执行器的当前实时队列大小在80%或接近极限的情况下创建警报。我认为我们可以从executor.getThreadPoolExecutor().getQueue().size();获得价值。我目前停留在如何实现这一目标上

4 个答案:

答案 0 :(得分:2)

@Controller
public class QueueMonitorController {

    @Autowired
    private Executor executor;

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

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

因此无需创意并建立自己的机制,它们都是内置的。基于Spring 4.2,但不应过分依赖该版本。


因此,根本目标是监视队列,并在队列已满80%时发送警报。这不应纳入您的代码中,该代码负责确保您的业务逻辑正常工作。您不应该在那里进行黑客攻击以解决资源不足的问题。如果您的想法是在打包队列时应该限制用户,那么还有更好的方法来处理这些用户。

由于该想法是进行“光监控”,即没有尝试处理,当队列已满80%时,轮询解决方案将足够轻量。考虑到执行程序可以轻松地注入到单独的Controller中,它甚至不会弄乱您的“真实”代码。

答案 1 :(得分:1)

由于ThreadPoolTaskExecutor没有公开任何API,因此您可以获取它使用的队列。但是,您可以自由扩展ThreadPoolTaskExecutor并创建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,您可以使用该方法获取队列。

答案 2 :(得分:0)

我不知道您从何处获得ThreadPoolTaskExecutor类执行程序。但是在Java中,您可以强制转换为ThreadPoolExecutor并获取队列,其大小如下:

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

答案 3 :(得分:0)

要实时地做到这一点并不容易。您需要修饰BlockingQueue的方法,以便可以添加代码以在队列内容更改时立即执行。

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

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

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