1. 序章

前の記事では、common.collectパッケージで導入された新機能の調査を開始しました。

この簡単な記事では、common.util.concurrentパッケージへの追加について説明します。

2. AtomicLongMap

並行シナリオでは、標準の HashMap は単に並行ではないため、実際にはうまく機能しない可能性があります。 この特定のシナリオでは、 AtomicLongMap は、スレッドセーフな方法でLong値を格納することで解決します。

AtomicLongMap は、ずっと前にGuava11で導入されました。 現在、4つの新しいメソッドが追加されています。

2.1. AccumulateAndGet()

accumulateAndGet()メソッドは、アキュムレータ関数を使用して既存の値とマージすることにより、キーにリンクされた値を更新します。 次に、更新された値を返します。

@Test
public void accumulateAndGet_withLongBinaryOperator_thenSuccessful() {
    long noOfStudents = 56;
    long oldValue = courses.get(SPRING_COURSE_KEY);

    long totalNotesRequired = courses.accumulateAndGet(
      "Guava", 
      noOfStudents, 
      (x, y) -> (x * y));

    assertEquals(totalNotesRequired, oldValue * noOfStudents);
}

2.2. getAndAccumulate()

このメソッドは上記で定義したものと同様の機能を備えていますが、更新された値ではなく古い値を返します(同じ操作の順序が示すように)。

2.3. updateAndGet()

updateAndGet()メソッドは、2番目のパラメーターとして提供された指定された関数を使用して、キーの現在の値を更新します。 次に、キーの更新された値を返します。

@Test
public void updateAndGet_withLongUnaryOperator_thenSuccessful() {
    long beforeUpdate = courses.get(SPRING_COURSE_KEY);
    long onUpdate = courses.updateAndGet(
      "Guava",
      (x) -> (x / 2));
    long afterUpdate = courses.get(SPRING_COURSE_KEY);

    assertEquals(onUpdate, afterUpdate);
    assertEquals(afterUpdate, beforeUpdate / 2);
}

2.4. getAndUpdate()

このメソッドはupdateAndGet()と非常によく似ていますが、更新されたキーではなく、古い値のキーを返します。

3. モニター

モニタークラスは、 ReentrantLock の代わりと見なされます。また、少し読みやすく、エラーが発生しにくくなっています。

3.1. Monitor.newGuard()

Guava 21は、 Monitor.Guard インスタンスを返す新しいメソッドnewGuard()を追加しました。これは、スレッドが待機できるブール条件として機能します。

public class MonitorExample {
    private List<String> students = new ArrayList<String>();
    private static final int MAX_SIZE = 100;

    private Monitor monitor = new Monitor();

    public void addToCourse(String item) throws InterruptedException {
        Monitor.Guard studentsBelowCapacity = monitor.newGuard(this::isStudentsCapacityUptoLimit);
        monitor.enterWhen(studentsBelowCapacity);
        try {
            students.add(item);
        } finally {
            monitor.leave();
        }
    }

    public Boolean isStudentsCapacityUptoLimit() {
        return students.size() > MAX_SIZE;
    }
}

4. MoreExecutors

このクラスには追加はありませんが、 sameThreadExecutor()APIは削除されています。 このメソッドはv18.0以降非推奨になり、代わりに directExecutor()または newDirectExecutorService()を使用することをお勧めします。

5. ForwardingBlockingDeque

ForwardingBlockingDeque は、 BlockingQueue が標準コレクションよりも並行コレクションタイプであるため、common.collectから移動された既存のクラスです。

6. 結論

Guava 21は、Java 8に対応するための新しいユーティリティを導入しようとしているだけでなく、既存のモデルをより意味のあるものに改善しようとしています。

そしていつものように、この記事のコードサンプルはGitHubリポジトリで入手できます。