java lambda使用

考虑到旧版Java代码,无论您在哪里看,带有lambda表达式的Java 8绝对可以提高质量和可读性。 今天,让我们看一下ReadWriteLock以及如何使它使用起来更简单。 假设我们有一个称为Buffer的类,它可以记住队列中的最后几条消息,对旧消息进行计数并丢弃。 实现非常简单:

public class Buffer {private final int capacity;private final Deque<String> recent;private int discarded;public Buffer(int capacity) {this.capacity = capacity;this.recent = new ArrayDeque<>(capacity);}public void putItem(String item) {while (recent.size() >= capacity) {recent.removeFirst();++discarded;}recent.addLast(item);}public List<String> getRecent() {final ArrayList<String> result = new ArrayList<>();result.addAll(recent);return result;}public int getDiscardedCount() {return discarded;}public int getTotal() {return discarded + recent.size();}public void flush() {discarded += recent.size();recent.clear();}}

现在我们可以putItem() ,但是内部recent队列将仅保留最后一个capacity元素。 但是,它也记住必须丢弃多少项以避免内存泄漏。 该类工作正常,但仅在单线程环境中有效。 我们使用不是线程安全的ArrayDeque和非同步的int 。 尽管对int读写是原子的,但不能保证更改在不同线程中可见。 同样,即使我们将线程安全的BlockingDequeAtomicInteger一起使用,我们仍然处于竞争状态的危险中,因为这两个变量彼此不同步。

一种方法是synchronize所有方法 ,但这似乎很严格。 此外,我们怀疑读取的数量大大超过写入的数量。 在这种情况下, ReadWriteLock是一个很好的选择。 它实际上包括两个锁-一个用于读取,一个用于写入。 实际上,它们都为同一把锁竞争,而同一把锁可以同时由一个作者或多个读者获得。 因此,当没有人在写并且只有写者偶尔阻塞所有读者时,我们可以进行并发读取。 使用synchronized将始终阻止所有其他对象,无论他们做什么。 ReadWriteLock的可悲部分是它引入了许多样板。 您必须显式打开一个锁,并记住在finally块中对其进行unlock() 。 我们的实现变得难以阅读:

public class Buffer {private final int capacity;private final Deque<String> recent;private int discarded;private final Lock readLock;private final Lock writeLock;public Buffer(int capacity) {this.capacity = capacity;recent = new ArrayDeque<>(capacity);final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();readLock = rwLock.readLock();writeLock = rwLock.writeLock();}public void putItem(String item) {writeLock.lock();try {while (recent.size() >= capacity) {recent.removeFirst();++discarded;}recent.addLast(item);} finally {writeLock.unlock();}}public List<String> getRecent() {readLock.lock();try {final ArrayList<String> result = new ArrayList<>();result.addAll(recent);return result;} finally {readLock.unlock();
}public int getDiscardedCount() {readLock.lock();try {return discarded;} finally {readLock.unlock();}}public int getTotal() {readLock.lock();try {return discarded + recent.size();} finally {readLock.unlock();}}public void flush() {writeLock.lock();try {discarded += recent.size();recent.clear();} finally {writeLock.unlock();}}}

这是在8月8日之前完成的方式。有效,安全且丑陋。 但是,使用lambda表达式,我们可以将横切关注点包装在这样的实用工具类中:

public class FunctionalReadWriteLock {private final Lock readLock;private final Lock writeLock;public FunctionalReadWriteLock() {this(new ReentrantReadWriteLock());}public FunctionalReadWriteLock(ReadWriteLock lock) {readLock = lock.readLock();writeLock = lock.writeLock();}public <T> T read(Supplier<T> block) {readLock.lock();try {return block.get();} finally {readLock.unlock();}}public void read(Runnable block) {readLock.lock();try {block.run();} finally {readLock.unlock();}}public <T> T write(Supplier<T> block) {writeLock.lock();try {return block.get();} finally {writeLock.unlock();}
public void write(Runnable block) {writeLock.lock();try {block.run();} finally {writeLock.unlock();}}}

如您所见,我们包装了ReadWriteLock并提供了一组可使用的实用程序方法。 原则上,我们希望传递一个RunnableSupplier<T> (具有单个T get()方法的接口),并确保调用它时已被适当的锁包围。 我们可以编写完全相同的包装器类,而无需使用lambda,但是使用它们可以大大简化客户端代码:

public class Buffer {private final int capacity;private final Deque<String> recent;private int discarded;private final FunctionalReadWriteLock guard;public Buffer(int capacity) {this.capacity = capacity;recent = new ArrayDeque<>(capacity);guard = new FunctionalReadWriteLock();}public void putItem(String item) {guard.write(() -> {while (recent.size() >= capacity) {recent.removeFirst();++discarded;}recent.addLast(item);});}public List<String> getRecent() {return guard.read(() -> {return recent.stream().collect(toList());});}public int getDiscardedCount() {return guard.read(() -> discarded);}public int getTotal() {return guard.read(() -> discarded + recent.size());}public void flush() {guard.write(() -> {discarded += recent.size();recent.clear();});}}

看看我们如何调用guard.read()guard.write()传递应该受到保护的代码段? 看起来很整洁。 顺便说一句,您是否注意到我们如何使用stream()将任何集合转换为任何其他集合(在这里: Deque into List stream() ? 现在,如果我们提取几个内部方法,则可以使用方法引用来进一步简化lambda:

public void flush() {guard.write(this::unsafeFlush);
}private void unsafeFlush() {discarded += recent.size();recent.clear();
}public List<String> getRecent() {return guard.read(this::defensiveCopyOfRecent);
}private List<String> defensiveCopyOfRecent() {return recent.stream().collect(toList());
}

这只是利用lambda表达式来改进现有代码和库的众多方法之一。 我们真的很高兴他们终于进入Java语言了,同时已经出现在其他数十种JVM语言中。

翻译自: https://www.javacodegeeks.com/2014/03/simplifying-readwritelock-with-java-8-and-lambdas.html

java lambda使用

java lambda使用_使用Java 8和Lambda简化ReadWriteLock相关推荐

  1. lambda表达式_在Java 7或更早版本中使用Java 8 Lambda表达式

    lambda表达式 我认为没有人会拒绝Java 8引入的Lambda表达式的有用性.但是,许多项目都停留在Java 7甚至旧版本上. 升级可能既耗时又昂贵. 如果第三方组件与Java 8不兼容,则可能 ...

  2. java 自定义表达式_自定义 Java Lambda

    用了这么久的 Java,也体验了 Java 8 的 lambda 带来的便捷,但是我一直都是直接用,而从未想过他是如何实现的.比如:为什么在小括号里面可以放一个函数作为参数,自己造一个lambda 应 ...

  3. java 复合方法_《Java 8 实战》Ch3: Lambda表达式(下):类型与限制、方法引用、复合...

    李文轩 2019-04-23 3.5 类型的检查和判断:变量捕获限制 类型检查 Lambda的类型是从使用Lambda的上下文推断出来的. Lambda表达式需要的类型称为目标类型 . Lambda表 ...

  4. java核心教程_核心Java教程

    java核心教程 Welcome to Core Java Tutorial. I have written a lot on Core Java and Java EE frameworks. Th ...

  5. java event 异步_[转]java异步编程

    很多时候我们都希望能够最大的利用资源,比如在进行IO操作的时候尽可能的避免同步阻塞的等待,因为这会浪费CPU的资源.如果在有可读的数据的时候能够通知程序执行读操作甚至由操作系统内核帮助我们完成数据的拷 ...

  6. java高级教程_高级Java教程

    java高级教程 课程大纲 学习Java基础很容易. 但是,真正钻研该语言并研究其更高级的概念和细微差别将使您成为一名出色的Java开发人员. 网络上充斥着"软","便宜 ...

  7. java正则表达式 匹配()_学习Java正则表达式(匹配、替换、查找)

    import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; public c ...

  8. java skip函数_【Java必修课】图说Stream中的skip()和limit()方法及组合使用

    1 简介 本文将讲解Java 8 Stream中的两个方法:skip()和limit().这两个方法是Stream很常用的,不仅各自会被高频使用,还可以组合出现,并能实现一些小功能,如subList和 ...

  9. java 包命名_【Java】包的命名规则

    命名规范 包:所有单词的字母小写,之后每个单词用-隔开,如 org.nemo.demo 常量:所有单词的字母大写,之后每个单词用_隔开,如 FLAG 类:所有单词的首字母大写,如 TestJava p ...

最新文章

  1. ImageView.ScaleType /android:scaleType值的意义区别
  2. OpenCV中的特征匹配+单应性以查找对象
  3. 500线电机光电码盘
  4. Batch Norm、Layer Norm、Instance Norm、Group Norm、Switchable Norm总结
  5. BF算法和KMP算法实现
  6. chrome ui源码剖析-Accelerator(快捷键)
  7. 【JQuery】on/off 绑定事件和解绑事件
  8. 使用nginx简单实现负载均衡
  9. Python机器学习:多项式回归与模型泛化009LASSO回归
  10. 217 - leetcode -存在重复元素 -数据结构类 先排序再操作
  11. directx最终用户运行时_WSL将支持GPU计算,并可运行Linux GUI应用
  12. matlab有限体积网格,用Matlab实现简单有限体积求解器
  13. Python数据结构与算法(2.2)——顺序表
  14. 贴片电容器容量怎么换算?
  15. 06【五险一金解读】还有你的工资条哦?
  16. 卡方检验的统计量推导_解释相关性的卡方检验的所有统计量 - Minitab
  17. AutoCAD .NET 二次开发实例(2) 批量统计指定图层线段长度
  18. 不知道考研那些书比较好么?我来推荐~~~(一)
  19. FingerGestures手势插件的使用
  20. STM8S003国产替代 DP32G003 32 位微控制器芯片

热门文章

  1. AtCoder Beginner Contest 179 总结
  2. 史上最全MySQL 大表优化方案(长文)
  3. Spring MVC的GET与POST请求url-pattern坑
  4. 单点登录终极方案之 CAS 应用及原理
  5. jQuery 基础教程 (四)之jQuery中的DOM操作
  6. 漫画:什么是ConcurrentHashMap
  7. win10安装dockerx docker的常见命令 可以子腾讯云上做做练习
  8. php 错误提示开启,php开启与关闭错误提示,php开启错误提示_PHP教程
  9. linux原有的文件系统扩展,原来linux不用LVM也能扩展文件系统
  10. inner join on 加条件和where加条件_SQL学习笔记 - GROUP BY / JOIN / UNION