Java并发限制。只允许一个请求进入

Java并发限制。只允许一个请求进入,java,concurrency,Java,Concurrency,我有长时间运行的代码,这些代码会被请求破坏,这会导致更高的资源使用率和不必要的并发问题。我的解决方案是有一个等待区,每个线程在那里等待一些预定义的时间。如果在线程等待时没有新请求,它将继续操作。任何新的请求都会再次重置时钟,我们会释放上一个线程 我以前使用过信号量和倒计时锁存器,但它们都不适用于这个特定场景。在我手工编写此代码之前,我想看看是否有一种标准的方法来执行此操作。保持控制的最整洁的方法是使用队列。现代的BlockingQueue类做得很好。然后,您可以通过改变队列的长度来调节流量 您将

我有长时间运行的代码,这些代码会被请求破坏,这会导致更高的资源使用率和不必要的并发问题。我的解决方案是有一个等待区,每个线程在那里等待一些预定义的时间。如果在线程等待时没有新请求,它将继续操作。任何新的请求都会再次重置时钟,我们会释放上一个线程


我以前使用过信号量和倒计时锁存器,但它们都不适用于这个特定场景。在我手工编写此代码之前,我想看看是否有一种标准的方法来执行此操作。

保持控制的最整洁的方法是使用队列。现代的BlockingQueue类做得很好。然后,您可以通过改变队列的长度来调节流量

您将一个作业发布到队列中,并让一个或多个线程坐在队列的另一端来完成所有工作,而不是自己实际完成工作

实际上,有一个结构已经为实现这个精确的体系结构做好了准备,它被称为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();
要限制请求,应该使用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);
           }
    }
});
我的解决方案是有一个等待区,每个线程在那里等待一些预定义的时间


您可以通过ThreadPoolExecutor免费获得此功能。例如,您可以分配1个核心线程和10个最大线程,然后指定例如5L,TimeUnit.MINUTES,这样,如果5个额外线程中的一个休眠5分钟,它将被关闭。请务必注意,不幸的是,除非队列已满,否则ThreadPoolExecutor启动的线程数不会超过核心线程数。因此,只有在队列中有100个东西之后,才能分配第二个线程。出于这个原因,我通常将core和max thread参数设置为相同的值。

我不理解您的描述。听起来,如果你不断收到新的请求,实际上没有一个会继续?这是一个潜在的问题,所以我们需要有一个故障保险箱。但实际上,在我的用例中,这种情况永远不会发生。长时间运行的代码到底是如何被请求破坏的?这是一种令人困惑的表达方式,长期运行操作这个术语通常适用于正在服务的单个请求。例如,将文本编辑器的内容写入磁盘。也许你应该添加更多用例的细节。你的编辑改变了问题的重点。请考虑接受我的回答并提出另一个问题。谢谢。在重新阅读我的问题后,我不得不同意,虽然你的回答似乎忽略了我的线程等待区短语,但我已经接受了你的回答,我也删除了我的编辑。ExecutorService为+1。它已经内置了9年,比自己手工编写代码要有效得多。+1表示阻塞队列。当我考虑节流时,我应该考虑一下。@doc_180-记住ExecutorService实际上只是一个阻塞队列和一个线程池,以一种经过尝试和测试的方式组合在一起。试试看——你会惊讶地发现你的代码变化如此之小。不过,我还有一个顾虑。我已经编辑了我的问题。我最初的问题似乎没有提出所有的事实和挑战。