我有长时间运行的代码,受到请求的影响,它导致更高的资源使用和不必要的并发问题.我的解决方案是像一个等待区域,每个线程等待一些预定义的时间.如果在线程等待时没有新请求,则继续执行该操作.任何新请求都将重新设置时钟并释放前一个线程.
我之前使用过信号量和倒计时锁存器,但它们都不适用于这种特定情况.在我编写代码之前,我想看看是否有一种标准的方法.
我有长时间运行的代码,受到请求的影响,它导致更高的资源使用和不必要的并发问题.
听起来你应该使用受限制的ExecutorService
.您应该拥有固定数量的线程,并且不会在新请求进入时创建新线程.然后,您可以通过调整池中的线程数来最大化吞吐量.
// only allow 10 concurrent requests
ExecutorService threadPool = Executors.newFixedThreadPool(10);
...
while (requestsComeIn) {
threadPool.submit(yourRunnableRequest);
}
// you need to shut the pool down once no more requests come in
threadPool.shutdown();
Run Code Online (Sandbox Code Playgroud)
要限制请求,您应该使用RejectedExecutionHandler
.类似下面的代码应该在队列中有100个元素之后使用哪些块:
BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(100);
ThreadPoolExecutor threadPool =
new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS, queue);
// we need our RejectedExecutionHandler to block if the queue is full
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
// this will block the producer until there's room in the queue
executor.getQueue().put(r);
} catch (InterruptedException e) {
throw new RejectedExecutionException(
"Unexpected InterruptedException", e);
}
}
});
Run Code Online (Sandbox Code Playgroud)
我的解决方案是像一个等待区域,每个线程等待一些预定义的时间.
你可以免费获得这个ThreadPoolExecutor
.例如,您可以分配1个核心线程和10个最大线程然后指定(例如),5L, TimeUnit.MINUTES
因此如果5个额外线程中的一个休眠5分钟,它将被关闭.值得注意的是,遗憾的是,除非队列已满,否则ThreadPoolExecutor
将不会启动核心线程以外的任务.因此,只有在队列中有100个内容之后才会分配第二个线程.出于这个原因,我通常使核心和最大线程参数值相同.