【问题标题】:Atomic update if current value is less than another value如果当前值小于另一个值,则进行原子更新
【发布时间】:2018-05-11 02:07:57
【问题描述】:

我正在寻找像 AtomicIntegerLongAddr 这样的东西:

  • 如果值小于MAX,则递增,其中MAX 是某个用户定义的值。
  • 返回一个值,指示原子是否增加。

用例:

  • 我有一个任务队列。
  • 只有MAX 任务应该同时运行。
  • 当一个新任务添加到队列中时,如果正在进行的任务数少于MAX,我想运行它

我不能使用AtomicIntegerLongAddr 的原因是它们只允许您与特定值而不是值范围进行比较。

澄清:我不希望解决方案实际执行任务。我的用例涉及将网络请求传递给 Jetty。它使用单个线程来驱动多个网络请求。任何触发Executor 的解决方案都无法达到此目的,因为这样我最终会为每个网络请求提供一个线程。

【问题讨论】:

  • 你可以使用 LinkedBlockingQueue 之类的东西来限制可以添加到队列中的项目数
  • @user7 我不想限制可以添加到队列中的项目数。我想将所有内容都排队,但一次只运行 MAX 任务。
  • 我不太明白你的用例。如果已经有 MAX-1 个活动任务,你会怎么做?
  • 工作完成后你会减少计数器吗?
  • @user7 是的。这就是计划。

标签: java atomic


【解决方案1】:

Andy Turner provided an excellent answer 但我发现这个解决方案更具可读性。本质上,我们只需要new Semaphore(MAX)Semaphore.tryAcquire()

如果您深入研究Semaphore 的源代码,您会发现其实现类似于安迪的答案。

这里是一些示例代码:

Semaphore semaphore = new Semaphore(MAX);
// ... much later ...
public void addTask(Runnable task)
{
  if (semaphore.tryAcquire())
    task.run();
  else
    queue.add(task);
}

public void afterTaskComplete(Runnable task)
{
  semaphore.release();
}

【讨论】:

    【解决方案2】:

    使用compareAndSet():

    boolean incrementToTheMax(AtomicInteger atomicInt, int max) {
      while (true) {
        int value = atomicInt.get();
        if (value >= max) {
          // The counter has already reached max, so don't increment it.
          return false;
        }
        if (atomicInt.compareAndSet(value, value+1)) {
          // If we reach here, the atomic integer still had the value "value";
          // and so we incremented it.
          return true;
        }
        // If we reach here, some other thread atomically updated the value.
        // Rats! Loop, and try to increment of again.
      }
    }
    

    【讨论】:

    • 是的,我认为这会起作用,但我希望避免自旋锁(出于性能原因)。也就是说,我刚刚打开了Semaphore 的源代码,你猜怎么着?他们做同样的事情。我想没有什么神奇的:)无论如何,我想我会坚持Semaphore,只是因为代码更容易理解。
    • @Gili 这里没有性能问题。这基本上就是AtomicInteger.incrementAndGet等的实现方式。
    猜你喜欢
    • 1970-01-01
    • 2016-01-17
    • 1970-01-01
    • 2019-03-18
    • 2018-04-12
    • 2019-05-28
    • 2016-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多