使用ReentrantLock和Lambdas进行干净同步

最近,我在阅读一篇内容丰富的文章,内容涉及Javin Paul 1 synchronizedReentrantLock之间的区别。 他强调了后者的优点,但并未保留一些缺点,这些缺点与正确使用所需的繁琐的try-finally块有关。

在同意他的陈述的同时,我沉迷于一个想法,当它涉及到同步时,这总是困扰着我。 两种方法混淆了单独的关注点- 同步和同步内容的功能 -妨碍了逐一测试这些关注点。

作为探索性类型,我为过去已经尝试过的该问题选择了解决方案。 但是那时我不太喜欢编程模式。 这是由于由于匿名类而导致的冗长。 但是手头有Java 8和Lambda表达式 ,我认为可能值得重新考虑。 因此,我复制了Javin Paul示例的“计数器”部分,编写了一个简单的测试用例,并开始进行重构。 这是最初的情况:

class Counter {private final Lock lock;private int count;Counter() {lock = new ReentrantLock();}int next() {lock.lock();try {return count++;} finally {lock.unlock();}}
}

可以清楚地看到丑陋的try-finally块,它在实际功能2周围产生了很多噪声。 想法是将此块移到其自己的类中,该类充当执行增量操作的一种同步方面。 下一个代码片段显示了这样一个新创建的Operation接口的外观,以及Lambda表达式3如何使用它:

class Counter {private final Lock lock;private int count;interface Operation<T> {T execute();}Counter() {lock = new ReentrantLock();}int next() {lock.lock();try {Operation<Integer> operation = () -> { return count++; };return operation.execute();} finally {lock.unlock();}}
}

在下面的类提取步骤中,引入了Synchronizer类型以用作执行程序,以确保在适当的同步范围内执行给定的Operation

class Counter {private final Synchronizer synchronizer;private int count;interface Operation<T> {T execute();}static class Synchronizer {private final Lock lock;Synchronizer() {lock = new ReentrantLock();}private int execute( Operation<Integer> operation ) {lock.lock();try {return operation.execute();} finally {lock.unlock();}}}Counter() {synchronizer = new Synchronizer();}int next() {return synchronizer.execute( () -> { return count++; } );}
}

如果我没有完全弄错的话,这应该和上课一样。 好吧,测试是绿色的,但是普通的JUnit测试通常对并发没有多大帮助。 但是,最后一次更改至少可以通过单元测试来验证正确的调用顺序,以确保同步:

public class Counter {final Synchronizer<Integer> synchronizer;final Operation<Integer> incrementer;private int count;public Counter( Synchronizer<Integer> synchronizer ) {this.synchronizer = synchronizer;this.incrementer = () -> { return count++; };}public int next() {return synchronizer.execute( incrementer );}
}

如您所见,“ Operation和“ Synchronizer已移至其自己的文件。 这样,提供了同步方面,并且可以作为单独的单元进行测试。 现在, Counter类使用构造函数注入同步器实例4 。 此外,增量操作已分配给名为“ incrementer”的字段。 为了简化测试,最终字段的可见性已默认打开。 使用Mockito进行例如监视同步器的测试现在可以确保正确的同步调用如下:

@Test
public void synchronization() {Synchronizer<Integer> synchronizer = spy( new Synchronizer<>() );Counter counter = new Counter( synchronizer );counter.next();verify( synchronizer ).execute( counter.incrementer );}

通常,对于使用方法调用验证,我不会太过退出,因为这会在单元和测试用例之间产生非常紧密的联系。 但是鉴于上述情况,对我来说这并不是一个太糟糕的妥协。 但是,我只是使用Java 8和Lambda表达式进行第一次热身,也许我在并发方面也缺少一些东西-那么您怎么看?

  1. ReentrantLock的实例在Java中,同步VS ReentrantLock的区别 ,Javin保罗,2013年3月7日↩
  2. 显然足够的噪声来迷惑我,因为我的第一个测试版失败... ↩
  3. 我决定使用类型参数返回值而不是int 。 这样,可以更好地重用所得的同步机制。 但是我不确定由于性能或其他原因,例如自动装箱在这里是否很重要。 因此,对于一般方法来说,可能还有更多需要考虑的事情,尽管things
  4. 如果由于某种原因无法更改构造函数,则可以引入一个委托的默认构造函数,该构造函数将Synchronizer的新实例注入到参数化的实例中,如下所示: this( new Synchronizer() ); 。 这种方法可能是用于测试目的的可接受的开销↩

翻译自: https://www.javacodegeeks.com/2014/04/clean-synchronization-using-reentrantlock-and-lambdas.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/364065.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 二维数组奇数金字塔_二维数组:奇数阶魔方 | 新思维:C语言程序设计

幻方&#xff0c;有时又称魔方&#xff0c;由一组排放在正方形中的整数组成&#xff0c;其每行、每列以及两条对角线上的数之和均相等。通常幻方由从到的连续整数组成。Siamese方法(Kraitchik 1942年&#xff0c;pp. 148-149)是构造奇数阶幻方的一种方法&#xff0c;说明如下&a…

react-性能优化

开发中遇到一个需要优化的性能&#xff0c;页面需要渲染很多table&#xff0c;而且可以自己添加table&#xff0c;所以就导致router改变时&#xff0c;清除这些DOM结构就会很慢&#xff0c;这就给用户造成不好的体验。 问题所在&#xff1a;清除渲染过多的DOM结构才导致迟缓&a…

Node.js学习(篇章一)

<node.js的特点> 采用了异步式I/O与事件驱动的架构设计&#xff0c;架构为单线程模型。 <supervisor包的作用> node.js开发项目&#xff0c;当修改项目时&#xff0c;需要终止进程重启Node.js之后才可以看到修改后的效果&#xff0c;为了解决这个问题&#xff0c;我…

WinXP启动时自动打开上次关机时未关闭的文件夹

不能自动打开上次关机时未关闭的文件夹解决方法&#xff1a; 首先运行注册表&#xff0c;解决方法&#xff1a;打开[\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced] 在右面的窗口中新建DWORD类型键值“PersistBrowsers”&#xff0c;数据为…

机器学习前沿02

自动机器学习 https://mbd.baidu.com/newspage/data/landingsuper?context%7B%22nid%22%3A%22news_9244479631915180647%22%7D&n_type1&p_from3 卷积网络的综述 https://mbd.baidu.com/newspage/data/landingsuper?context%7B%22nid%22%3A%22news_979691604239366144…

java 判断闰年和月份_java----根据输入的年月判断闰年和打印日历

import java.util.Scanner;import java.text.ParseException;import java.util.Calendar;public class Calendar {public static void main(String[] args) throws ParseException {Scanner sc new Scanner(System.in);System.out.println("请输入年份&#xff1a;"…

反应灵敏且性能卓越的Spray + Akka解决方案,以“在Java和Node.js中发挥并发性和性能”...

在我以前的文章中&#xff0c;我研究了一个虚拟的交易引擎&#xff0c;并将基于Java的阻止解决方案与基于Node.js的非阻止解决方案进行了比较。 在文章的结尾&#xff0c;我写道&#xff1a; 我怀疑在Node.js近期取得成功之后&#xff0c;越来越多的异步Java库将开始出现。 这…

百度蜘蛛(BaiduSpider)IP段详细情况介绍

123.125.68.*这个蜘蛛经常来,别的来的少,表示网站可能要进入沙盒了&#xff0c;或被者降权。 220.181.68.*每天这个IP 段只增不减很有可能进沙盒或K站。 220.181.7.*、123.125.66.* 代表百度蜘蛛IP造访&#xff0c;准备抓取你东西。 121.14.89.*这个ip段作为度过新站考察期。 2…

iframe关于滚动条的去除和保留

iframe嵌入页面后&#xff0c;我们有时需要调整滚动条&#xff0c;例如&#xff0c;去掉全部的滚动条&#xff0c;去掉右边的滚动条且保留底下的滚动条&#xff0c;去掉底下的滚动条且保留右边的滚动条。那么我们应该怎么做呢&#xff1f; 一&#xff1a;去掉全部的滚动条 第一…

拷贝构造函数与赋值函数(运算符重载)(1)

拷贝构造函数拷贝构造函数在三种情况下会被使用1.使用对象来初始化对象时2.当函数的形参是对象时3.当函数的返回值为对象时 2,3情况的本质还是1 //Test1.h #include<iostream> using namespace std; class ST { private:int a;long b; public:ST(int a0, long b0):a(a),…

GOOGLE不让我访问啦?

GOOGLE不让我访问啦? 今天上GOOGLE出现了这么一个画面,可是我就是不知道我的电脑到底中了什么毒,平常我没上什么特殊的网站,也没下载什么软件,因为这电脑我只用来做些基本的开发和看看园子里的文章而已.真不知道是怎么一回事.posted on 2007-05-05 12:46 黄尚 阅读(...) 评论(…

java条件执行方法_java 开启多线程里面如何加条件判断执行其他逻辑?

方法1&#xff1a;通过Thread类中的isAlive()方法判断线程是否处于活动状态。线程启动后&#xff0c;只要没有运行完毕&#xff0c;都会返回true。【注】如果只是要等其他线程运行结束之后再继续操作&#xff0c;可以执行t.join()&#xff0c;即&#xff1a;在t执行完毕前挂起。…

使用Jenkins / Hudson远程API检查作业状态

在进行演讲时&#xff0c;我写了一个Hudson / Jenkins插件&#xff08;适用于EclipseCon NA 2014&#xff09; &#xff0c;但我想发表有关演讲中提到的想法的博客文章。 在这篇文章中&#xff0c;我解释了如何在不使用Web界面的情况下与CI服务器进行交互。 Jenkins / Hudson远…

大数据分析和人工智能科普

一、大数据 1.1 大数据&#xff08;Big Data&#xff09; 众说纷纭&#xff01; 个人认为&#xff0c;大数据中的“大”&#xff0c;不仅仅是涉及数据规模&#xff0c;而且包含“价值“这个层面。其实无非就是大量的信息罢了&#xff0c;但是我们却能 通过各种手段从这些信息中…

Redis API的使用与理解

一、Redis 基础&#xff1a; 1、通用命令&#xff1a; keys [pattern]&#xff1a; keys * #遍历所有key&#xff1b;keys he* #以he开头的key&#xff1b; keys he[a-e]* #以‘he’开头第三个字母是a-e之间&#xff1b; keys ph? #?代码一位&#xff0c;以ph开头且字母是…

点击底部input输入框,弹出的软键盘挡住input(苹果手机使用第三方输入法 )

测试移动端页面的时候&#xff0c;偶然发现点击底部input输入框时&#xff0c;弹出的虚拟键盘偶尔会挡住input输入框。 输入框固定在页面底部&#xff0c;如图所示&#xff1a; input固定底部设计图.png点击底部input输入框唤起软键盘时&#xff0c;软键盘挡住输入框。如图所示…

java采集温湿度水浸_机房水浸传感器:智能生活不可或缺的漏水传感器

原标题&#xff1a;机房水浸传感器&#xff1a;智能生活不可或缺的漏水传感器智能化的飞速发展让人们的生活发生了重大改变&#xff0c;为保证机房的安全、稳定、高效运行&#xff0c;网络设备的良好运行状态和设备使用寿命与安全&#xff0c;通常会对网络运行环境的电力供应、…

以编程方式访问Java基本类型的大小

许多不熟悉Java的开发人员首先要了解的一件事是Java的基本原始数据类型 &#xff0c;其固定&#xff08;与平台无关&#xff09;的大小&#xff08;以位或字节为单位用二进制补码表示 &#xff09;以及它们的范围&#xff08;Java中所有数字类型都是带符号的&#xff09; &…

oracle用EXPLAIN PLAN 分析SQL语句

EXPLAIN PLAN 是一个很好的分析SQL语句的工具,它甚至可以在不执行SQL的情况下分析语句. 通过分析,我们就可以知道ORACLE是怎么样连接表,使用什么方式扫描表(索引扫描或全表扫描)以及使用到的索引名称. 你需要按照从里到外,从上到下的次序解读分析的结果. EXPLAIN PLAN分析的结果…

创建型模式:原型模式

个人公众号原文&#xff1a;创建型模式&#xff1a;原型模式 五大创建型模式之五&#xff1a;原型模式。 简介 姓名 &#xff1a;原型模式 英文名 &#xff1a;Prototype Pattern 价值观 &#xff1a;效率第一 个人介绍 &#xff1a; Specify the kinds of objects to create u…