Java : Condition (同期) - API使用例
Condition (Java SE 19 & JDK 19) の使用例まとめです。
だいたいのメソッドを網羅済みです。
API仕様のおともにどうぞ。
概要
Condition インタフェースは、Lock による同期処理において Object.wait, notify に相当する機能を実現します。
// 基準となる時刻
final long current = System.nanoTime();
// 基準となる時刻からの差分を秒として取得
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;
try (var executor = Executors.newSingleThreadExecutor()) {
final var lock = new ReentrantLock();
final var cond = lock.newCondition();
executor.submit(() -> {
System.out.printf("lock ... (%f sec.)%n", elapsedTime.getAsDouble());
lock.lock();
try {
System.out.printf("await ... (%f sec.)%n", elapsedTime.getAsDouble());
cond.await();
System.out.printf("await OK! (%f sec.)%n", elapsedTime.getAsDouble());
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
} finally {
lock.unlock();
}
});
TimeUnit.SECONDS.sleep(5);
lock.lock();
try {
System.out.printf("signal! (%f sec.)%n", elapsedTime.getAsDouble());
cond.signal();
} finally {
lock.unlock();
}
}
// 結果
// ↓
//lock ... (0.003795 sec.)
//await ... (0.006260 sec.)
//signal! (5.019196 sec.)
//await OK! (5.019534 sec.)
メソッド
void await ()
// 基準となる時刻
final long current = System.nanoTime();
// 基準となる時刻からの差分を秒として取得
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;
try (var executor = Executors.newSingleThreadExecutor()) {
final var lock = new ReentrantLock();
final var cond = lock.newCondition();
executor.submit(() -> {
System.out.printf("lock ... (%f sec.)%n", elapsedTime.getAsDouble());
lock.lock();
try {
System.out.printf("await ... (%f sec.)%n", elapsedTime.getAsDouble());
cond.await();
System.out.printf("await OK! (%f sec.)%n", elapsedTime.getAsDouble());
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
} finally {
lock.unlock();
}
});
TimeUnit.SECONDS.sleep(5);
lock.lock();
try {
System.out.printf("signal! (%f sec.)%n", elapsedTime.getAsDouble());
cond.signal();
} finally {
lock.unlock();
}
}
// 結果
// ↓
//lock ... (0.003795 sec.)
//await ... (0.006260 sec.)
//signal! (5.019196 sec.)
//await OK! (5.019534 sec.)
boolean await (long time, TimeUnit unit)
// 基準となる時刻
final long current = System.nanoTime();
// 基準となる時刻からの差分を秒として取得
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;
try (var executor = Executors.newSingleThreadExecutor()) {
final var lock = new ReentrantLock();
final var cond = lock.newCondition();
executor.submit(() -> {
System.out.printf("lock ... (%f sec.)%n", elapsedTime.getAsDouble());
lock.lock();
try {
System.out.printf("await ... (%f sec.)%n", elapsedTime.getAsDouble());
final var ret = cond.await(2, TimeUnit.SECONDS);
System.out.printf("await ret = %b (%f sec.)%n", ret, elapsedTime.getAsDouble());
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
} finally {
lock.unlock();
}
});
TimeUnit.SECONDS.sleep(1);
lock.lock();
try {
System.out.printf("signal! (%f sec.)%n", elapsedTime.getAsDouble());
cond.signal();
} finally {
lock.unlock();
}
}
// 結果
// ↓
//lock ... (0.003034 sec.)
//await ... (0.004681 sec.)
//signal! (1.007004 sec.)
//await ret = true (1.007422 sec.)
タイムアウトする例です。
// 基準となる時刻
final long current = System.nanoTime();
// 基準となる時刻からの差分を秒として取得
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;
try (var executor = Executors.newSingleThreadExecutor()) {
final var lock = new ReentrantLock();
final var cond = lock.newCondition();
executor.submit(() -> {
System.out.printf("lock ... (%f sec.)%n", elapsedTime.getAsDouble());
lock.lock();
try {
System.out.printf("await ... (%f sec.)%n", elapsedTime.getAsDouble());
final var ret = cond.await(2, TimeUnit.SECONDS);
System.out.printf("await ret = %b (%f sec.)%n", ret, elapsedTime.getAsDouble());
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
} finally {
lock.unlock();
}
});
TimeUnit.SECONDS.sleep(3);
}
// 結果
// ↓
//lock ... (0.001920 sec.)
//await ... (0.002397 sec.)
//await ret = false (2.015032 sec.)
long awaitNanos (long nanosTimeout)
// 基準となる時刻
final long current = System.nanoTime();
// 基準となる時刻からの差分を秒として取得
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;
try (var executor = Executors.newSingleThreadExecutor()) {
final var lock = new ReentrantLock();
final var cond = lock.newCondition();
executor.submit(() -> {
System.out.printf("lock ... (%f sec.)%n", elapsedTime.getAsDouble());
lock.lock();
try {
System.out.printf("await ... (%f sec.)%n", elapsedTime.getAsDouble());
final var ret = cond.awaitNanos(TimeUnit.SECONDS.toNanos(2));
System.out.printf("await ret = %d (%f sec.)%n", ret, elapsedTime.getAsDouble());
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
} finally {
lock.unlock();
}
});
TimeUnit.SECONDS.sleep(1);
lock.lock();
try {
System.out.printf("signal! (%f sec.)%n", elapsedTime.getAsDouble());
cond.signal();
} finally {
lock.unlock();
}
}
// 結果
// ↓
//lock ... (0.002420 sec.)
//await ... (0.003724 sec.)
//signal! (1.003412 sec.)
//await ret = 1000114200 (1.003748 sec.)
タイムアウトする例です。
// 基準となる時刻
final long current = System.nanoTime();
// 基準となる時刻からの差分を秒として取得
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;
try (var executor = Executors.newSingleThreadExecutor()) {
final var lock = new ReentrantLock();
final var cond = lock.newCondition();
executor.submit(() -> {
System.out.printf("lock ... (%f sec.)%n", elapsedTime.getAsDouble());
lock.lock();
try {
System.out.printf("await ... (%f sec.)%n", elapsedTime.getAsDouble());
final var ret = cond.awaitNanos(TimeUnit.SECONDS.toNanos(2));
System.out.printf("await ret = %d (%f sec.)%n", ret, elapsedTime.getAsDouble());
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
} finally {
lock.unlock();
}
});
TimeUnit.SECONDS.sleep(3);
}
// 結果
// ↓
//lock ... (0.000975 sec.)
//await ... (0.001143 sec.)
//await ret = -15962300 (2.017199 sec.)
void awaitUninterruptibly ()
InterruptedException が発生しない、ということ以外については await() の使用例をご参照ください。
try (var executor = Executors.newSingleThreadExecutor()) {
final var lock = new ReentrantLock();
final var cond = lock.newCondition();
final var future = executor.submit(() -> {
System.out.println("lock ...");
lock.lock();
try {
System.out.println("await ...");
cond.awaitUninterruptibly();
System.out.println("await OK!");
System.out.println("isInterrupted : " + Thread.currentThread().isInterrupted());
} finally {
lock.unlock();
}
});
TimeUnit.SECONDS.sleep(1);
final var ret = future.cancel(true);
System.out.println("cancel = " + ret);
lock.lock();
try {
System.out.println("signal!");
cond.signal();
} finally {
lock.unlock();
}
}
// 結果
// ↓
//lock ...
//await ...
//cancel = true
//signal!
//await OK!
//isInterrupted : true
try (var executor = Executors.newSingleThreadExecutor()) {
final var lock = new ReentrantLock();
final var cond = lock.newCondition();
final var future = executor.submit(() -> {
System.out.println("lock ...");
lock.lock();
try {
System.out.println("await ...");
cond.await();
System.out.println("await OK!");
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
} finally {
lock.unlock();
}
});
TimeUnit.SECONDS.sleep(1);
final var ret = future.cancel(true);
System.out.println("cancel = " + ret);
}
// 結果
// ↓
//lock ...
//await ...
//InterruptedException!
//cancel = true
boolean awaitUntil (Date deadline)
// 基準となる時刻
final long current = System.nanoTime();
// 基準となる時刻からの差分を秒として取得
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;
final var deadline = Instant.now().plusSeconds(2);
try (var executor = Executors.newSingleThreadExecutor()) {
final var lock = new ReentrantLock();
final var cond = lock.newCondition();
executor.submit(() -> {
System.out.printf("lock ... (%f sec.)%n", elapsedTime.getAsDouble());
lock.lock();
try {
System.out.printf("await ... (%f sec.)%n", elapsedTime.getAsDouble());
final var ret = cond.awaitUntil(Date.from(deadline));
System.out.printf("await ret = %b (%f sec.)%n", ret, elapsedTime.getAsDouble());
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
} finally {
lock.unlock();
}
});
TimeUnit.SECONDS.sleep(1);
lock.lock();
try {
System.out.printf("signal! (%f sec.)%n", elapsedTime.getAsDouble());
cond.signal();
} finally {
lock.unlock();
}
}
// 結果
// ↓
//lock ... (0.003268 sec.)
//await ... (0.004692 sec.)
//signal! (1.007036 sec.)
//await ret = true (1.007370 sec.)
タイムアウトする例です。
// 基準となる時刻
final long current = System.nanoTime();
// 基準となる時刻からの差分を秒として取得
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;
final var deadline = Instant.now().plusSeconds(2);
try (var executor = Executors.newSingleThreadExecutor()) {
final var lock = new ReentrantLock();
final var cond = lock.newCondition();
executor.submit(() -> {
System.out.printf("lock ... (%f sec.)%n", elapsedTime.getAsDouble());
lock.lock();
try {
System.out.printf("await ... (%f sec.)%n", elapsedTime.getAsDouble());
final var ret = cond.awaitUntil(Date.from(deadline));
System.out.printf("await ret = %b (%f sec.)%n", ret, elapsedTime.getAsDouble());
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
} finally {
lock.unlock();
}
});
TimeUnit.SECONDS.sleep(3);
}
// 結果
// ↓
//lock ... (0.000794 sec.)
//await ... (0.000954 sec.)
//await ret = false (2.012004 sec.)
void signal ()
このメソッドの使用例は、await() にまとめて記載しました。
そちらのAPI使用例をご参照ください。
void signalAll ()
// 基準となる時刻
final long current = System.nanoTime();
// 基準となる時刻からの差分を秒として取得
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;
try (var executor = Executors.newFixedThreadPool(3)) {
final var lock = new ReentrantLock();
final var cond = lock.newCondition();
for (int i = 1; i <= 3; i++) {
final var id = i;
TimeUnit.MILLISECONDS.sleep(100);
executor.submit(() -> {
lock.lock();
try {
System.out.printf("%d : await ... (%f sec.)%n", id, elapsedTime.getAsDouble());
cond.await();
System.out.printf("%d : await OK! (%f sec.)%n", id, elapsedTime.getAsDouble());
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
} finally {
lock.unlock();
}
});
}
TimeUnit.SECONDS.sleep(5);
lock.lock();
try {
System.out.printf("signal all! (%f sec.)%n", elapsedTime.getAsDouble());
cond.signalAll();
} finally {
lock.unlock();
}
}
// 結果
// ↓
//1 : await ... (0.105841 sec.)
//2 : await ... (0.213281 sec.)
//3 : await ... (0.321265 sec.)
//signal all! (5.330418 sec.)
//1 : await OK! (5.330721 sec.)
//2 : await OK! (5.330926 sec.)
//3 : await OK! (5.331123 sec.)
signal メソッドを使う例です。
// 基準となる時刻
final long current = System.nanoTime();
// 基準となる時刻からの差分を秒として取得
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;
try (var executor = Executors.newFixedThreadPool(3)) {
final var lock = new ReentrantLock();
final var cond = lock.newCondition();
for (int i = 1; i <= 3; i++) {
final var id = i;
TimeUnit.MILLISECONDS.sleep(100);
executor.submit(() -> {
lock.lock();
try {
System.out.printf("%d : await ... (%f sec.)%n", id, elapsedTime.getAsDouble());
cond.await();
System.out.printf("%d : await OK! (%f sec.)%n", id, elapsedTime.getAsDouble());
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
} finally {
lock.unlock();
}
});
}
TimeUnit.SECONDS.sleep(5);
for (int i = 0; i < 3; i++) {
lock.lock();
try {
System.out.printf("signal! (%f sec.)%n", elapsedTime.getAsDouble());
cond.signal();
} finally {
lock.unlock();
}
TimeUnit.SECONDS.sleep(2);
}
}
// 結果
// ↓
//1 : await ... (0.105298 sec.)
//2 : await ... (0.214365 sec.)
//3 : await ... (0.324142 sec.)
//signal! (5.332321 sec.)
//1 : await OK! (5.332855 sec.)
//signal! (7.369622 sec.)
//2 : await OK! (7.369812 sec.)
//signal! (9.384503 sec.)
//3 : await OK! (9.384861 sec.)
関連記事
- API 使用例
- BlockingQueue (ブロッキング・キュー)
- Callable
- CancellationException
- ConcurrentHashMap.KeySetView (並列処理用セット)
- ConcurrentLinkedDeque (並列処理用・両端キュー)
- ConcurrentLinkedQueue (並列処理用キュー)
- ConcurrentMap (並列処理用マップ)
- ConcurrentModificationException (並列処理例外)
- ConcurrentSkipListSet (並列処理用セット)
- CopyOnWriteArrayList (並列処理用リスト)
- CopyOnWriteArraySet (並列処理用セット)
- CountDownLatch (同期)
- CyclicBarrier (同期)
- Exchanger (同期)
- Executor
- ExecutorService
- Executors
- Future
- Future.State
- FutureTask
- InterruptedException (割込み例外)
- Lock (同期)
- Object (オブジェクト)
- Runnable
- Semaphore (セマフォ)
- Thread (スレッド)
- ThreadGroup
- ThreadLocal
- TimeUnit