点击上方“码农突围”,马上关注

这里是码农充电第一站,回复“666”,获取一份专属大礼包

真爱,请设置“星标”或点个“在看

文章来源:https://juejin.cn/post/7130883974846480391

目录

1.延迟队列

2.时间格式的天数

3. 印戳锁

4. 并行累加器

5. 十六进制格式

6. 数组的二分法检索

7. 位图

8. 移相器

在本文中,你可以了解一些可能没有听说过的有用的 Java 特性。这是我最近使用的功能的私人列表,或者是我在阅读有关 Java 的文章时偶然发现的。我不会关注语言方面,而是关注 API。

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类。

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.时间格式的天数

【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);

这是我的结果。当然结果取决于在一天中的时间。

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);
}

4. 并行累加器

【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;

5. 十六进制格式

【Hex Format】

有时我们需要在十六进制格式的字符串、字节或字符之间进行转换。从 Java 17 开始,您可以使用 HexFormat 类。只需创建一个 HexFormat 实例,然后您就可以格式化例如输入 byte 到十六进制字符串的表。你也可以例如将输入的十六进制字符串解析为字节表,如下所示。

HexFormat format = HexFormat.of();byte[] input = new byte[] {127, 0, -50, 105};
String hex = format.formatHex(input);
System.out.println(hex);byte[] output = format.parseHex(hex);
assert Arrays.compare(input, output) == 0;

6. 数组的二分法检索

【Binary Search for Arrays】

假设我们想在排序表中插入一个新元素。Arrays.binarySearch() 返回搜索键的索引(如果包含)。否则,它返回一个i插入点,我们可以使用它来计算新键的索引:-(insertion point)-1。此外,binarySearch 方法是在 Java 中查找已排序数组中元素的最简单、最有效的方法。

示例如下,我们有一个输入表,其中四个元素按升序排列。我们想在此表中插入数字“3”。这是我们如何计算插入点的索引的方法。

int[] t = new int[] {1, 2, 4, 5};
int x = Arrays.binarySearch(t, 3);assert ~x == 2;

7. 位图

【Bit Set】

如果我们需要对位数组执行一些操作怎么办?你会为此使用``boolean[]??有一种更有效和内存效率更高的方法来实现它。它是 BitSet 类。BitSet 类允许我们存储和操作位数组。与 boolean[]  相比,它消耗的内存少了 8 倍。我们可以对数组执行逻辑操作,例如andorxor`。

假设我们有两个输入位数组。我们想对它们执行xor 操作。事实上,只返回那些元素的操作,这些元素只插入一个数组,而不是另一个数组。为此,我们需要创建两个“BitSet”实例并在其中插入示例元素,如下所示。最后应该在 BitSet 实例之一上调用 xor 方法。它将第二个 BitSet实例作为参数。

BitSet bs1 = new BitSet();
bs1.set(0);
bs1.set(2);
bs1.set(4);
System.out.println("bs1 : " + bs1);BitSet bs2 = new BitSet();
bs2.set(1);
bs2.set(2);
bs2.set(3);
System.out.println("bs2 : " + bs2);bs2.xor(bs1);
System.out.println("xor: " + bs2);

这是运行上面可见的代码后的结果。

8. 移相器

【Phaser】

和这里的其他一些例子一样,它也是 Java Concurrent 包的元素。它被称为“移相器”。它与更知名的 CountDownLatch 非常相似。但是,它提供了一些附加功能。它允许我们设置在继续执行之前需要等待的动态线程数。使用“Phaser”,定义的线程数需要在屏障上等待,然后才能进入下一步执行。多亏了这一点,我们可以协调执行的多个阶段。

在下面的示例中,我们设置了 50 个线程的屏障,以便在进入下一个执行阶段之前到达。然后我们创建一个线程,在Phaser 实例上调用方法arriveAndAwaitAdvance()。它阻塞线程,直到所有 50 个线程都不会到达屏障。然后它进入 phase-1 并调用方法 arriveAndAwaitAdvance()

Phaser phaser = new Phaser(50);
Runnable r = () -> {System.out.println("phase-0");phaser.arriveAndAwaitAdvance();System.out.println("phase-1");phaser.arriveAndAwaitAdvance();System.out.println("phase-2");phaser.arriveAndDeregister();
};ExecutorService executor = Executors.newFixedThreadPool(50);
for (int i = 0; i < 50; i++) {executor.submit(r);
}

这是执行上面可见的代码后的结果。

(完)
码农突围资料链接1、卧槽!字节跳动《算法中文手册》火了,完整版 PDF 开放下载!
2、计算机基础知识总结与操作系统 PDF 下载
3、艾玛,终于来了!《LeetCode Java版题解》.PDF
4、Github 10K+,《LeetCode刷题C/C++版答案》出炉.PDF欢迎添加鱼哥个人微信:smartfish2020,进粉丝群或围观朋友圈。

干货 | Java8的几个实用新特性教程分享给你相关推荐

  1. Java8新特性教程 - 终极指南

    转载来源:https://www.javacodegeeks.com/2014/05/java-8-features-tutorial.html Java 8 新特性教程 - 终极指南 编者按:在这篇 ...

  2. mysql is双竖线_MySQL 5.0 新特性教程 存储过程:第二讲

    MySQL 5.0 新特性教程 存储过程:第二讲推荐查看本文HTML版本 什么样的SQL语句在Mysql存储过程中才是合法的呢?你可以创建一个包含INSERT, UPDATE,DELETE, SELE ...

  3. java8 stream 做累加_Java8新特性之Stream(上)|乐字节

    上次给大家介绍了Java8新特性之方法引用,大家可以点击回顾下.接下来小乐继续给大家带来Java8新特性之Stream ,流是Java8最重要的内容,小乐准备分上下两部分介绍,今天是上部. 5.1.什 ...

  4. 聊聊 Java8 以后各个版本的新特性

    [这是 ZY 第 11 篇原创技术文章] 某天在网上闲逛,突然看到有篇介绍 Java 11 新特性的文章,顿时心里一惊,毕竟我对于 Java 的版本认识还停留在 Java 8 上,而日常使用的语法和 ...

  5. java8 lambda map排序_Java8新特性第3章(Stream API)

    转载请注明出处:https://zhuanlan.zhihu.com/p/20540202 Stream作为Java8的新特性之一,他与Java IO包中的InputStream和OutputStre ...

  6. Java8 和 Java9 的主要新特性

    Java 8 的主要新特性 1. Lambda 表达式 Lambda 允许把函数作为一个方法的参数传递进方法中. 作用:解决 Java 被诟病的匿名内部类的问题. 2. 接口中可增加了默认方法 作用: ...

  7. 宋利兵 mysql_《MySQL 5.7 Replication新特性》分享之互动问题解答

    分享主题 <MySQL 5.7 Replication新特性> 嘉宾介绍 宋利兵,MySQL研发工程师.2009年加入MySQL全球研发团队,从事MySQL复制相关功能的开发. 主题介绍 ...

  8. MySQL 5.0 新特性教程 触发器:第一讲

    滥觞:网海拾贝 作者:mysql AB;翻译:陈朋奕 Conventions and Styles约定和编程作风 每次我想要演示实践代码时,我会对mysql客户真个屏幕就出现的代码阻止调解排解,将字体 ...

  9. java8 collect 类型转换_Java 8 新特性 Stream类的collect方法

    1.Collectors.toList():转换成List集合./ Collectors.toSet():转换成set集合. System.out.println(Stream.of("a& ...

最新文章

  1. 洛谷P1613 跑路
  2. linux下使用binfmt_misc设定不同二进制的打开程序
  3. 计算机组成原理实验认识多思网络虚拟实验系统_3D全息投影,裸眼3D,全息互动投影系统...
  4. matlab 判断元素索引_matlab – 获取矩阵中n个最大元素的索引
  5. 芒果云接吗_芒果糯米饭是生产力的关键吗?
  6. 计算机系统结构安全检测,信息安全体系结构安全测评实验报告.doc
  7. 嘘!你与谷歌语音助手的对话,可能已经泄露……
  8. matlab 工具函数(一) —— 添加指定 SNR 的噪声
  9. Kubernetes Scheduler Deep Dive
  10. 常用1寸,2寸照片标准尺寸
  11. 【学习笔记】计算机网络-DNS层次查询
  12. 智能分析网关微信端告警消息推送的开发流程
  13. python ---input()函数、前几篇知识点总结
  14. 机器学习之L1、L2的区别与相关数学基础知识
  15. Redisson闭锁
  16. 高防服务器防御中“清洗”是什么意思
  17. 点击文本框弹出热门标签
  18. 2023年,重新扬帆起航!
  19. 水彩画工具JixiPix Aquarella for Mac
  20. 元宇宙,会成为下一代互联网的主场吗?

热门文章

  1. 2021最新Java面试笔试题目分享
  2. 国庆七连测(一)BREAD
  3. STC 下载 自动波特率 设计
  4. 400个可以发外链的网站
  5. 实验三——密码破解技术
  6. vue3中使用swiper7轮播图插件
  7. 银河麒麟V10操控系统Qt安装
  8. 《安富莱嵌入式周报》第276期:2022.07.25--2022.07.31
  9. CdTe量子点及与牛血清蛋白的偶联/CdTe量子点与CLV3信号多肽片段偶联/GSH-CdTe量子点与溶菌酶的偶联
  10. 为什么lol进服务器时显示错误,《lol手游》显示authenticationerror怎么解决 异常问题解决方法...