Java8的几个实用新特性

Java8的几个实用新特性

1.延迟队列

【Delay Queue】
Java 中有许多类型的集合可用。但你听说了DelayQueue吗?它是一种特定类型的 Java 集合,它允许我们根据元素的延迟时间对元素进行排序。

尽管 DelayQueue该类是 Java 集合的成员,但它属于 java.util.concurrent 包。它实现了BlockingQueue接口。只有当元素的时间到期时,才能从队列中取出元素。

为了使用它,首先在类里面需要实现接口中的getDelay方法Delayed。它不必是一个类——你也可以使用 Java Record。

public record DelayedEvent(long startTime, String msg) implements Delayed {

    public long getDelay(TimeUnit unit) {
        long diff = startTime - System.currentTimeMillis();
        return unit.convert(diff, TimeUnit.MILLISECONDS);
    }

    public int compareTo(Delayed o) {
        return (int) (this.startTime - ((DelayedEvent) o).startTime);
    }

}

假设我们想推迟元素10秒。我们只需要设置当前时间增加了10秒DelayedEvent类。
Java8的几个实用新特性_第1张图片
上面可见代码的输出是什么?让我们来看看。
Java8的几个实用新特性_第2张图片
2.时间格式的天数

【Period of Days in Time Format】
Java 8 改进了很多时间处理 API。从这个版本的 Java 开始,在大多数情况下,可能不必使用任何额外的库,如 Joda Time。你能想象从 Java 16 开始,你甚至可以使用标准格式化程序来表示一天中的时段,例如“早上”或“下午”?有一种称为 B 的新格式模式。

String s = DateTimeFormatter
  .ofPattern("B")
  .format(LocalDateTime.now());
System.out.println(s);

这是我的结果。当然结果取决于在一天中的时间。
在这里插入图片描述
Java8的几个实用新特性_第3张图片
3. 印戳锁

【StampedLock】

Java Concurrent 是最有趣的 Java 包之一。同时,它也是开发人员鲜为人知的一种,尤其是当他们主要使用 Web 框架时。有多少人曾经在 Java 中使用过锁?锁定是一种比“同步”块更灵活的线程同步机制。从 Java 8 开始,您可以使用一种称为“StampedLock”的新型锁。StampedLock 是使用 ReadWriteLock 的替代方法。它允许对读取操作进行乐观锁定。此外,它比 ReentrantReadWriteLock 具有更好的性能。

假设我们有两个线程。其中第一个更新余额,而第二个读取余额的当前值。为了更新余额,我们当然需要先读取它的当前值。我们在这里需要某种同步,假设第一个线程同时运行多次。第二个线程只是说明了如何使用乐观锁进行读取操作。

StampedLock lock = new StampedLock();
Balance b = new Balance(10000);
Runnable w = () -> {
   long stamp = lock.writeLock();
   b.setAmount(b.getAmount() + 1000);
   System.out.println("Write: " + b.getAmount());
   lock.unlockWrite(stamp);
};
Runnable r = () -> {
   long stamp = lock.tryOptimisticRead();
   if (!lock.validate(stamp)) {
      stamp = lock.readLock();
      try {
         System.out.println("Read: " + b.getAmount());
      } finally {
         lock.unlockRead(stamp);
      }
   } else {
      System.out.println("Optimistic read fails");
   }
};

现在,让我们通过同时运行两个线程 50 次来测试它。它应该按预期工作 - 余额的最终值为60000。

ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 50; i++) {
   executor.submit(w);
   executor.submit(r);
}
  1. 并行累加器

【Concurrent accumulators】
锁并不是 Java Concurrent 包中唯一有趣的特性。另一种称为并发累加器。还有并发加法器,但它是一个非常相似的功能。LongAccumulator(也有DoubleAccumulator)使用提供的函数更新值。它允许我们在许多场景中实现无锁算法。当多个线程更新一个公共值时,通常最好使用 AtomicLong。

让我们看看它是如何工作的。为了创建它,您需要在构造函数中设置两个参数。第一个是用于计算累加结果的函数。通常,您会使用sum 方法。第二个参数表示我们的累加器的初始值。

现在,让我们使用初始值10000 创建LongAccumulator,然后从多个线程调用accumulate()方法。最终结果是什么?

LongAccumulator balance = new LongAccumulator(Long::sum, 10000L);
Runnable w = () -> balance.accumulate(1000L);

ExecutorService executor = Executors.newFixedThreadPool(50);
for (int i = 0; i < 50; i++) {
   executor.submit(w);
}

executor.shutdown();
if (executor.awaitTermination(1000L, TimeUnit.MILLISECONDS))
   System.out.println("Balance: " + balance.get());
assert balance.get() == 60000L;

你可能感兴趣的:(java,java)