乐趣区

关于next:NextjsReactNode系统实战搞定SSR服务器渲染一起无mi

1. 提早队列

download:https://www.sisuoit.com/2811….

 复制下哉 ZY:https://www.sisuoit.com/2811.html

咱们都晓得,在 Java 中有类型泛滥的汇合。那么你据说过 DelayQueue 吗?它是一个非凡类型的 Java 汇合,容许咱们依据元素的延迟时间对其进行排序。坦率来讲,这是一个十分有意思的类。只管 DelayQueue 类是 Java 汇合的成员之一,然而它位于 java.util.concurrent 包中。它实现了 BlockingQueue 接口。只有当元素的工夫过期时,能力从队列中取出。

要应用这个汇合,首先,咱们的类须要实现 Delayed 接口的 getDelay 办法。当然,它不肯定必须是类,也能够是 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 秒钟,那么咱们只须要在 DelayedEvent 类上将工夫设置成以后工夫加上 10 秒钟即可。

final DelayQueue<DelayedEvent> delayQueue = new DelayQueue<>();
final long timeFirst = System.currentTimeMillis() + 10000;
delayQueue.offer(new DelayedEvent(timeFirst, "1"));
log.info("Done");
log.info(delayQueue.take().msg());

对于下面的代码,咱们可能看到什么输入呢?如下所示。

2. 工夫格局中反对显示一天中的时段

好吧,我抵赖这个 Java 个性对于你们中的大多数人来讲并没有太大的用途,然而,我对这个个性情有独钟……Java 8 对工夫解决 API 做了很多的改良。从这个版本的 Java 开始,在大多数状况下,咱们都不须要任何额定的库来解决工夫了,比方 Joda Time。你可能设想不到,从 Java 16 开始,咱们甚至能够应用规范的格式化器来表白一天中的时段,也就是“in the morning”或者“in the afternoon”。这是一个新的格局模式,叫做 B。

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

如下是我运行的后果。当然,你的后果可能会因工夫不同而有所差别。

好,稍等……当初,你可能会问这个格局为什么叫做 B。事实上,对于这种类型的格局来讲,它不是最直观的名字。但兴许上面的表格可能解决咱们所有的纳闷。它是 DateTimeFormatter 可能解决的模式字符和符号的片段。我猜测,B 是第一个闲暇进去的字母。当然,我可能是错的。

3.StampedLock

我认为,Java Concurrent 是最乏味的 Java 包之一。同时,它也是一个不太为开发者所熟知的包,当开发人员次要应用 web 框架的时候更是如此。咱们有多少人已经在 Java 中应用过锁呢?锁是一种比 synchronized 块更灵便的线程同步机制。从 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);
}

4. 并发累加器

在 Java Concurrent 包中,有意思的并不仅仅有锁,另外一个很有意思的货色是并发累加器(concurrent accumulator)。咱们也有并发的加法器(concurrent adder),但它们的性能十分相似。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;
退出移动版