Contents

Guava 21 中Concurrent的新功能

1. 简介

在上一篇文章 中,我们开始探索common.collect包中引入的新功能。

在这篇快速文章中,让我们来看看 common.util.concurrent包的新增内容。

2. AtomicLongMap

在并发场景中,标准HashMap可能无法很好地工作,因为它根本不是并发的。在这种特殊情况下,AtomicLongMap通过以线程安全的方式存储Long值来帮助您。

AtomicLongMap很久以前在 Guava 11 中引入。现在,添加了四个新方法。

2.1. accumulatorAndGet()

*accumulatorAndGet()*方法通过使用累加器函数将其与现有值合并来更新与键链接的值。然后,它返回更新后的值:

@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()*方法使用作为第二个参数提供的指定函数更新键的当前值。然后,它返回键的更新值:

@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. updateAndGet()

此方法的工作方式与*updateAndGet()*非常相似,但它返回键的旧值而不是更新后的值。

3. Monitor

监视器类被视为ReentrantLock的替代品,它更具可读性且不易出错。

3.1. Monitor.newGuard()

Guava 21 添加了一个新方法——newGuard() ——它返回一个Monitor.Guard实例,用作线程可以等待的布尔条件:

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

这个类中没有添加,但相同的ThreadExecutor() API 已被删除。此方法自 v18.0 起已弃用,建议改用directExecutor()newDirectExecutorService()

5. ForwardingBlockingDeque

ForwardingBlockingDeque是一个现有的类,它已从common.collect移出,因为BlockingQueue更像是一种并发集合类型而不是标准集合。