Java Concurrency Throttling.只允许一个请求

unc*_*ons 0 java concurrency

我有长时间运行的代码,受到请求的影响,它导致更高的资源使用和不必要的并发问题.我的解决方案是像一个等待区域,每个线程等待一些预定义的时间.如果在线程等待时没有新请求,则继续执行该操作.任何新请求都将重新设置时钟并释放前一个线程.

我之前使用过信号量和倒计时锁存器,但它们都不适用于这种特定情况.在我编写代码之前,我想看看是否有一种标准的方法.

Gra*_*ray 5

我有长时间运行的代码,受到请求的影响,它导致更高的资源使用和不必要的并发问题.

听起来你应该使用受限制的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个内容之后才会分配第二个线程.出于这个原因,我通常使核心和最大线程参数值相同.