com.google.common.util.concurrent.Monitor类的使用及代码示例

x33g5p2x  于2022-01-25 转载在 其他  
字(14.3k)|赞(0)|评价(0)|浏览(173)

本文整理了Java中com.google.common.util.concurrent.Monitor类的一些代码示例,展示了Monitor类的具体用法。这些代码示例主要来源于Github/Stackoverflow/Maven等平台,是从一些精选项目中提取出来的代码,具有较强的参考意义,能在一定程度帮忙到你。Monitor类的具体详情如下:
包路径:com.google.common.util.concurrent.Monitor
类名称:Monitor

Monitor介绍

[英]A synchronization abstraction supporting waiting on arbitrary boolean conditions.

This class is intended as a replacement for ReentrantLock. Code using Monitoris less error-prone and more readable than code using ReentrantLock, without significant performance loss. Monitor even has the potential for performance gain by optimizing the evaluation and signaling of conditions. Signaling is entirely implicit. By eliminating explicit signaling, this class can guarantee that only one thread is awakened when a condition becomes true (no "signaling storms" due to use of java.util.concurrent.locks.Condition#signalAll) and that no signals are lost (no "hangs" due to incorrect use of java.util.concurrent.locks.Condition#signal).

A thread is said to occupy a monitor if it has entered the monitor but not yet left. Only one thread may occupy a given monitor at any moment. A monitor is also reentrant, so a thread may enter a monitor any number of times, and then must leave the same number of times. The enter and leave operations have the same synchronization semantics as the built-in Java language synchronization primitives.

A call to any of the enter methods with void return type should always be followed immediately by a try/finally block to ensure that the current thread leaves the monitor cleanly:

monitor.enter();finally  
monitor.leave(); 
} 
}

A call to any of the enter methods with boolean return type should always appear as the condition of an if statement containing a try/finally block to ensure that the current thread leaves the monitor cleanly:

if (monitor.tryEnter()) finally  
monitor.leave(); 
} 
} else  
// do other things since the monitor was not available 
} 
}

Comparison with synchronized and ReentrantLock

The following examples show a simple threadsafe holder expressed using synchronized, ReentrantLock, and Monitor.

synchronized

This version is the fewest lines of code, largely because the synchronization mechanism used is built into the language and runtime. But the programmer has to remember to avoid a couple of common bugs: The wait() must be inside a while instead of an if, and notifyAll() must be used instead of notify() because there are two different logical conditions being awaited.

public class SafeBox V result = value; 
value = null; 
notifyAll(); 
return result; 
} 
public synchronized void set(V newValue) throws InterruptedException  
while (value != null)  
wait(); 
} 
value = newValue; 
notifyAll(); 
} 
} 
}

ReentrantLock

This version is much more verbose than the synchronized version, and still suffers from the need for the programmer to remember to use while instead of if. However, one advantage is that we can introduce two separate Condition objects, which allows us to use signal() instead of signalAll(), which may be a performance benefit.

public class SafeBox V result = value; 
value = null; 
valueAbsent.signal(); 
return result; 
} finally  
lock.unlock(); 
} 
} 
public void set(V newValue) throws InterruptedException  
lock.lock(); 
try  
while (value != null)  
valueAbsent.await(); 
} 
value = newValue; 
valuePresent.signal(); 
} finally  
lock.unlock(); 
} 
} 
} 
}

Monitor

This version adds some verbosity around the Guard objects, but removes that same verbosity, and more, from the get and set methods. Monitor implements the same efficient signaling as we had to hand-code in the ReentrantLock version above. Finally, the programmer no longer has to hand-code the wait loop, and therefore doesn't have to remember to use while instead of if.

public class SafeBox }; 
private final Monitor.Guard valueAbsent = new Monitor.Guard(monitor)  
public boolean isSatisfied()  
return value == null; 
} 
}; 
private V value; 
public V get() throws InterruptedException  
monitor.enterWhen(valuePresent); 
try  
V result = value; 
value = null; 
return result; 
} finally  
monitor.leave(); 
} 
} 
public void set(V newValue) throws InterruptedException  
monitor.enterWhen(valueAbsent); 
try  
value = newValue; 
} finally  
monitor.leave(); 
} 
} 
} 
}

[中]支持等待任意布尔条件的同步抽象。
此类旨在替代ReentrantLock。与使用ReentrantLock的代码相比,使用Monitoris的代码不太容易出错,可读性也更高,而且没有显著的性能损失。Monitor甚至可以通过优化条件的评估和信号来提高性能。信令完全是implicit。通过消除显式信号,该类可以保证在条件变为真时只唤醒一个线程(由于使用java.util.concurrent.locks.condition#signalAll而没有“信号风暴”),并且没有信号丢失(由于不正确使用java.util.concurrent.locks.condition#signal而没有“挂起”)。
如果线程已进入监视器但尚未离开,则称其占用监视器。在任何时候,只有一个线程可以占用给定的监视器。监视器也是可重入的,因此线程可以多次进入监视器,然后必须离开相同的次数。enter和leave操作与内置Java语言同步原语具有相同的同步语义。
调用任何具有void return type的enter方法后,都应立即执行try/finally块,以确保当前线程干净地离开监视器:

monitor.enter();finally  
monitor.leave(); 
} 
}

对布尔返回类型的任何enter方法的调用应始终作为包含try/finally块的if语句的条件出现,以确保当前线程干净地离开监视器:

if (monitor.tryEnter()) finally  
monitor.leave(); 
} 
} else  
// do other things since the monitor was not available 
} 
}

与synchronized和ReentrantLock的比较
以下示例显示了一个使用synchronized、ReentrantLock和Monitor表示的简单线程安全保持架。
####同步的
这个版本的代码行数最少,这主要是因为所使用的同步机制内置于语言和运行时中。但是程序员必须记住避免几个常见的错误:wait()必须在一段时间内,而不是if;notifyAll()必须使用,而不是notify(),因为等待的是两种不同的逻辑条件。

public class SafeBox V result = value; 
value = null; 
notifyAll(); 
return result; 
} 
public synchronized void set(V newValue) throws InterruptedException  
while (value != null)  
wait(); 
} 
value = newValue; 
notifyAll(); 
} 
} 
}

####可重入锁定
这个版本比同步版本要详细得多,而且程序员仍然需要记住使用while而不是if。然而,一个优点是我们可以引入两个单独的条件对象,这允许我们使用signal()而不是signalAll(),这可能是一个性能优势。

public class SafeBox V result = value; 
value = null; 
valueAbsent.signal(); 
return result; 
} finally  
lock.unlock(); 
} 
} 
public void set(V newValue) throws InterruptedException  
lock.lock(); 
try  
while (value != null)  
valueAbsent.await(); 
} 
value = newValue; 
valuePresent.signal(); 
} finally  
lock.unlock(); 
} 
} 
} 
}

####监视器
此版本在Guard对象周围添加了一些详细信息,但从get和set方法中删除了相同的详细信息,以及更多内容。Monitor实现了与上面的ReentrantLock版本相同的高效信号传递。最后,程序员不再需要手工编写等待循环的代码,因此不必记住使用while而不是if。

public class SafeBox }; 
private final Monitor.Guard valueAbsent = new Monitor.Guard(monitor)  
public boolean isSatisfied()  
return value == null; 
} 
}; 
private V value; 
public V get() throws InterruptedException  
monitor.enterWhen(valuePresent); 
try  
V result = value; 
value = null; 
return result; 
} finally  
monitor.leave(); 
} 
} 
public void set(V newValue) throws InterruptedException  
monitor.enterWhen(valueAbsent); 
try  
value = newValue; 
} finally  
monitor.leave(); 
} 
} 
} 
}

代码示例

代码示例来源:origin: google/guava

/** Enters this monitor when the guard is satisfied. Blocks indefinitely. */
public void enterWhenUninterruptibly(Guard guard) {
 if (guard.monitor != this) {
  throw new IllegalMonitorStateException();
 }
 final ReentrantLock lock = this.lock;
 boolean signalBeforeWaiting = lock.isHeldByCurrentThread();
 lock.lock();
 boolean satisfied = false;
 try {
  if (!guard.isSatisfied()) {
   awaitUninterruptibly(guard, signalBeforeWaiting);
  }
  satisfied = true;
 } finally {
  if (!satisfied) {
   leave();
  }
 }
}

代码示例来源:origin: google/guava

/**
 * Enters this monitor if the guard is satisfied. Blocks at most the given time acquiring the
 * lock, but does not wait for the guard to be satisfied.
 *
 * @return whether the monitor was entered, which guarantees that the guard is now satisfied
 */
@SuppressWarnings("GoodTime") // should accept a java.time.Duration
public boolean enterIf(Guard guard, long time, TimeUnit unit) {
 if (guard.monitor != this) {
  throw new IllegalMonitorStateException();
 }
 if (!enter(time, unit)) {
  return false;
 }
 boolean satisfied = false;
 try {
  return satisfied = guard.isSatisfied();
 } finally {
  if (!satisfied) {
   lock.unlock();
  }
 }
}

代码示例来源:origin: google/guava

@Override
public final void awaitRunning() {
 monitor.enterWhenUninterruptibly(hasReachedRunning);
 try {
  checkCurrentState(RUNNING);
 } finally {
  monitor.leave();
 }
}

代码示例来源:origin: google/guava

void awaitStopped() {
 monitor.enterWhenUninterruptibly(stoppedGuard);
 monitor.leave();
}

代码示例来源:origin: google/guava

/**
 * Attempts to start the timer immediately prior to the service being started via {@link
 * Service#startAsync()}.
 */
void tryStartTiming(Service service) {
 monitor.enter();
 try {
  Stopwatch stopwatch = startupTimers.get(service);
  if (stopwatch == null) {
   startupTimers.put(service, Stopwatch.createStarted());
  }
 } finally {
  monitor.leave();
 }
}

代码示例来源:origin: google/guava

@GuardedBy("lock")
private void await(Guard guard, boolean signalBeforeWaiting) throws InterruptedException {
 if (signalBeforeWaiting) {
  signalNextWaiter();
 }
 beginWaitingFor(guard);
 try {
  do {
   guard.condition.await();
  } while (!guard.isSatisfied());
 } finally {
  endWaitingFor(guard);
 }
}

代码示例来源:origin: google/guava

@GuardedBy("lock")
private void awaitUninterruptibly(Guard guard, boolean signalBeforeWaiting) {
 if (signalBeforeWaiting) {
  signalNextWaiter();
 }
 beginWaitingFor(guard);
 try {
  do {
   guard.condition.awaitUninterruptibly();
  } while (!guard.isSatisfied());
 } finally {
  endWaitingFor(guard);
 }
}

代码示例来源:origin: com.ning.billing/killbill-osgi-bundles-analytics

/**
 * Exactly like guard.isSatisfied(), but in addition signals all waiting threads in the
 * (hopefully unlikely) event that isSatisfied() throws.
 */
@GuardedBy("lock")
private boolean isSatisfied(Guard guard) {
 try {
  return guard.isSatisfied();
 } catch (Throwable throwable) {
  signalAllWaiters();
  throw Throwables.propagate(throwable);
 }
}

代码示例来源:origin: google/guava

/**
 * Enters this monitor when the guard is satisfied. Blocks indefinitely, but may be interrupted.
 *
 * @throws InterruptedException if interrupted while waiting
 */
public void enterWhen(Guard guard) throws InterruptedException {
 if (guard.monitor != this) {
  throw new IllegalMonitorStateException();
 }
 final ReentrantLock lock = this.lock;
 boolean signalBeforeWaiting = lock.isHeldByCurrentThread();
 lock.lockInterruptibly();
 boolean satisfied = false;
 try {
  if (!guard.isSatisfied()) {
   await(guard, signalBeforeWaiting);
  }
  satisfied = true;
 } finally {
  if (!satisfied) {
   leave();
  }
 }
}

代码示例来源:origin: google/guava

/** Caller should check before calling that guard is not satisfied. */
 @GuardedBy("lock")
 private boolean awaitNanos(Guard guard, long nanos, boolean signalBeforeWaiting)
   throws InterruptedException {
  boolean firstTime = true;
  try {
   do {
    if (nanos <= 0L) {
     return false;
    }
    if (firstTime) {
     if (signalBeforeWaiting) {
      signalNextWaiter();
     }
     beginWaitingFor(guard);
     firstTime = false;
    }
    nanos = guard.condition.awaitNanos(nanos);
   } while (!guard.isSatisfied());
   return true;
  } finally {
   if (!firstTime) {
    endWaitingFor(guard);
   }
  }
 }
}

代码示例来源:origin: google/guava

@CanIgnoreReturnValue
@Override
public final Service stopAsync() {
 if (monitor.enterIf(isStoppable)) {
  try {
   State previous = state();
   switch (previous) {
    case NEW:
     snapshot = new StateSnapshot(TERMINATED);
     enqueueTerminatedEvent(NEW);
     break;
    case STARTING:
     snapshot = new StateSnapshot(STARTING, true, null);
     enqueueStoppingEvent(STARTING);
     doCancelStart();
     break;
   notifyFailed(shutdownFailure);
  } finally {
   monitor.leave();
   dispatchListenerEvents();

代码示例来源:origin: google/guava

@CanIgnoreReturnValue
@Override
public final Service startAsync() {
 if (monitor.enterIf(isStartable)) {
  try {
   snapshot = new StateSnapshot(STARTING);
   enqueueStartingEvent();
   doStart();
  } catch (Throwable startupFailure) {
   notifyFailed(startupFailure);
  } finally {
   monitor.leave();
   dispatchListenerEvents();
  }
 } else {
  throw new IllegalStateException("Service " + this + " has already been started");
 }
 return this;
}

代码示例来源:origin: google/guava

monitor.enter();
try {
    new IllegalStateException(
      "Cannot notifyStarted() when the service is " + snapshot.state);
  notifyFailed(failure);
  throw failure;
  doStop();
 } else {
  snapshot = new StateSnapshot(RUNNING);
  enqueueRunningEvent();
 monitor.leave();
 dispatchListenerEvents();

代码示例来源:origin: google/guava

/**
 * Implementing classes should invoke this method once their service has stopped. It will cause
 * the service to transition from {@link State#STARTING} or {@link State#STOPPING} to {@link
 * State#TERMINATED}.
 *
 * @throws IllegalStateException if the service is not one of {@link State#STOPPING}, {@link
 *     State#STARTING}, or {@link State#RUNNING}.
 */
protected final void notifyStopped() {
 monitor.enter();
 try {
  State previous = state();
  switch (previous) {
   case NEW:
   case TERMINATED:
   case FAILED:
    throw new IllegalStateException("Cannot notifyStopped() when the service is " + previous);
   case RUNNING:
   case STARTING:
   case STOPPING:
    snapshot = new StateSnapshot(TERMINATED);
    enqueueTerminatedEvent(previous);
    break;
  }
 } finally {
  monitor.leave();
  dispatchListenerEvents();
 }
}

代码示例来源:origin: google/guava

/**
 * Invoke this method to transition the service to the {@link State#FAILED}. The service will
 * <b>not be stopped</b> if it is running. Invoke this method when a service has failed critically
 * or otherwise cannot be started nor stopped.
 */
protected final void notifyFailed(Throwable cause) {
 checkNotNull(cause);
 monitor.enter();
 try {
  State previous = state();
  switch (previous) {
   case NEW:
   case TERMINATED:
    throw new IllegalStateException("Failed while in state:" + previous, cause);
   case RUNNING:
   case STARTING:
   case STOPPING:
    snapshot = new StateSnapshot(FAILED, false, cause);
    enqueueFailedEvent(previous, cause);
    break;
   case FAILED:
    // Do nothing
    break;
  }
 } finally {
  monitor.leave();
  dispatchListenerEvents();
 }
}

代码示例来源:origin: google/guava

@Override
public final void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException {
 if (monitor.enterWhenUninterruptibly(isStopped, timeout, unit)) {
  try {
   checkCurrentState(TERMINATED);
  } finally {
   monitor.leave();
  }
 } else {
  // It is possible due to races the we are currently in the expected state even though we
  // timed out. e.g. if we weren't event able to grab the lock within the timeout we would never
  // even check the guard. I don't think we care too much about this use case but it could lead
  // to a confusing error message.
  throw new TimeoutException(
    "Timed out waiting for "
      + this
      + " to reach a terminal state. "
      + "Current state: "
      + state());
 }
}

代码示例来源:origin: google/guava

void awaitStopped(long timeout, TimeUnit unit) throws TimeoutException {
 monitor.enter();
 try {
  if (!monitor.waitForUninterruptibly(stoppedGuard, timeout, unit)) {
   throw new TimeoutException(
     "Timeout waiting for the services to stop. The following "
       + "services have not stopped: "
       + Multimaps.filterKeys(servicesByState, not(in(EnumSet.of(TERMINATED, FAILED)))));
  }
 } finally {
  monitor.leave();
 }
}

代码示例来源:origin: com.ning.billing/killbill-osgi-bundles-jruby

@Deprecated
@Override
public final ListenableFuture<State> start() {
 if (monitor.enterIf(isStartable)) {
  try {
   snapshot = new StateSnapshot(STARTING);
   starting();
   doStart();
  } catch (Throwable startupFailure) {
   notifyFailed(startupFailure);
  } finally {
   monitor.leave();
   executeListeners();
  }
 }
 return startup;
}

代码示例来源:origin: google/guava

private void runWaitTest() {
 assertFalse(Thread.currentThread().isInterrupted());
 assertFalse(monitor.isOccupiedByCurrentThread());
 monitor.enter();
 try {
  assertTrue(monitor.isOccupiedByCurrentThread());
  doWaitScenarioSetUp();
  boolean interruptedBeforeCall = Thread.currentThread().isInterrupted();
  Outcome actualOutcome = doCall();
  boolean occupiedAfterCall = monitor.isOccupiedByCurrentThread();
  boolean interruptedAfterCall = Thread.currentThread().isInterrupted();
  assertEquals(expectedOutcome, actualOutcome);
  assertTrue(occupiedAfterCall);
  assertEquals(
    interruptedBeforeCall && expectedOutcome != Outcome.INTERRUPT, interruptedAfterCall);
 } finally {
  guard.setSatisfied(true);
  monitor.leave();
  assertFalse(monitor.isOccupiedByCurrentThread());
 }
}

代码示例来源:origin: stackoverflow.com

private final Monitor monitor = new Monitor();
private final Monitor.Guard paused = new Monitor.Guard(monitor) {
  @Override
  monitor.enterWhenUninterruptibly(notPaused);
  try {
    monitor.waitForUninterruptibly(notPaused);
  } finally {
    monitor.leave();
  monitor.enterIf(notPaused);
  try {
    isPaused = true;
  } finally {
    monitor.leave();
  monitor.enterIf(paused);
  try {
    isPaused = false;
  } finally {
    monitor.leave();

相关文章