英文:
Measure time a tasks waits in queue before being executed Java ThreadPoolExecutor
问题
我有一个使用阻塞队列的ThreadPoolExecutor,我正在尝试调试一个问题,我怀疑任务在被执行之前在ThreadPoolExecutor的队列中停留的时间太长。我正在尝试验证这个理论,想知道从入队到执行前监视长度的最佳方法是什么。
英文:
I have a ThreadPoolExecutor using a blocking queue and I am trying to debug an issue where I suspect tasks are being stuck too long in the ThreadPoolExecutor's queue for too long before being executed. I'm trying to validate this theory and was wondering what the best way to monitor the length from being enqueued to right before it is executed.
答案1
得分: 3
我偶尔使用的一个技巧是添加“追踪器”任务来测量它们在队列中等待的时间。要测量时间,记录任务添加时的时间戳,并与任务开始运行时的时间戳进行比较。最简单的形式如下:
long time = System.nanoTime();
executorService.submit(() -> {
System.out.println("Queued for " + (System.nanoTime() - time));
});
如果您主要关心等待时间超过固定阈值的任务,比如需要在一定时间限制内获取响应,那么这是一个不错的解决方案。追踪器任务在队列中等待的时间与真实任务一样长。如果您设置了1分钟的超时时间,每30秒添加一个追踪器任务可以让您很好地了解队列等待时间接近1分钟。而且这种方法非常容易实现,您可以将这种技巧应用于任何现有的执行器服务。
但是这只能告诉您在提交此任务时任务在队列中等待的时间,这可能过于粗粒度。如果您需要知道每个提交的任务的排队时间,并且愿意自定义执行器服务的实现,您可以做更多的事情:
-
您可以创建一个包含时间测量的自定义ExecutorService实现。当通过
submit
或invoke
方法添加任务时,记录任务的当前时间。当任务运行时,计算并记录排队时间,例如在beforeExecute方法中。 -
或者,您可以创建一个包含时间测量的自定义工作队列实现。当添加任务时,它会记录任务的当前时间戳,并在移除任务时将当前时间戳与任务的时间戳进行比较。
英文:
A trick I've used occasionally is to add "tracer" tasks that measure the time they spend in the queue. To measure the time, take the timestamp of when the task is added, and compare it with the timestamp of when the task starts running. The simplest possible form is:
long time = System.nanoTime();
executorService.submit(() -> {
System.out.println("Queued for " + System.nanoTime() - time);
});
This is a good solution if you mainly care about the tasks waiting for longer than a fixed threshold, like if you need the response within a certain time limit. The tracer tasks wait in the queue just as long as the real tasks. If you have a timeout of 1 minute, adding a tracer every 30 seconds gives you a pretty good idea of how close the queueing time is to 1 minute. It's also very easy to implement, you can apply the technique to any existing executor service.
This can only tell you how long tasks are waiting in the queue at the time when you submitted this task, which may too coarse-grained. If you need to know the queueing time for every task you submit, and you are willing to customize the executor service implementation, you can do more things:
-
You can create a custom ExecutorService implementation that includes time measurements. When tasks are added through the
submit
orinvoke
method you record the current time with the task. When the task runs, you calculate and log the queueing time, for example in the beforeExecute method -
Or, you can create a custom work queue implementation that incorporates time measurements. When a task is added, it would record the current timestamp with the task, and when a task is removed, it would compare the current timestamp with the task's timestamp.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论