0

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

我以前使用过信号量和倒计时锁存器,但它们都不适用于这种特殊情况。在我手动编写代码之前,我想看看是否有标准的方法来做这件事。

4

2 回答 2

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();

要限制请求,您应该使用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 个东西之后,才会分配第二个线程。出于这个原因,我通常将核心和最大线程参数设置为相同的值。

于 2013-10-01T16:22:19.450 回答
2

保持控制的最简洁的方法是使用队列。现代BlockingQueue班做得很好。然后,您可以通过改变队列的长度来限制。

与其自己实际完成工作,不如将 a 发布Job到队列中,并让一个或多个线程坐在队列的另一端完成所有工作。

实际上有一个现成的结构来实现这种精确的架构,它被称为ExecutorService. 其他地方有很多使用的例子。

有关详细信息,请参阅ExecutorService

于 2013-10-01T16:21:15.970 回答