假设我有这个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();
获得价值。我目前停留在如何实现这一目标上
答案 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
}
};