番石榴条纹类的细粒度并发

这篇文章将介绍如何使用Guava中的Striped类来实现更细粒度的并发。 ConcurrentHashMap使用条带化锁定方法来增加并发性,并且Striped类通过赋予我们具有条带化Locks , ReadWriteLocks和Semaphores的能力来扩展此主体。 当访问对象或数据结构(例如Array或HashMap)时,通常我们将在整个对象或数据结构上进行同步,但这是否总是必要的? 在某些情况下,答案是肯定的,但有时我们可能没有达到这种程度的进程锁定,并且可以通过使用更精细的方法来提高应用程序的性能。

条纹锁定/信号量的用例

始终同步可能的最小部分代码被视为最佳实践。 换句话说,我们只想在更改共享数据的代码部分之间进行同步。 通过允许我们减少不同任务的同步,条带化使这一步骤更进一步。 例如,假设我们有一个表示远程资源的URL的ArrayList,并且我们想限制在任何给定时间访问这些资源的线程总数。 限制对N个线程的访问自然适合java.util.concurrent.Semaphore对象。 但是问题在于限制对我们ArrayList的访问成为瓶颈。 这是Striped类提供帮助的地方。 我们真正想要做的是限制对资源的访问,而不是对URL的容器的访问。 假设每一个都是不同的,我们使用一种“条带化”的方法,其中一次访问每个 URL仅限于N个线程,从而提高了应用程序的吞吐量和响应能力。

创建条纹锁/信号灯

要创建Striped实例,我们只需使用Striped类中可用的静态因子方法之一即可。 例如,这是我们如何创建带区卷ReadWriteLock的实例:

Striped<ReadWriteLock> rwLockStripes = Striped.readWriteLock(10);

在上面的示例中,我们创建了一个Striped实例,在该实例中急切创建了单独的“条纹”,强引用。 影响是除非删除Striped对象本身,否则不会垃圾收集锁/信号灯。 但是,当创建锁/信号量时,Stranded类为我们提供了另一个选择:

int permits = 5;
int numberStripes = 10;
Striped<Semaphore> lazyWeakSemaphore = Striped.lazyWeakSemaphore(numberStripes,permits);

在此示例中, Semaphore实例将被延迟创建并包装在WeakReferences因此可立即用于垃圾回收,除非有另一个对象挂在其上。

访问/使用条纹锁/信号灯

要使用之前创建的Striped ReadWriteLock ,请执行以下操作:

String key = "taskA";
ReadWriteLock rwLock = rwLockStripes.get(key);
try{rwLock.lock();.....
}finally{rwLock.unLock();
}

通过调用Striped.get方法,我们将返回一个与给定对象键相对应的ReadWriteLock实例。 我们将在下面使用Striped类提供更多示例。

锁/信号量检索保证

当检索锁/信号量实例时,Striped类保证objectA等于objectB(假设正确实现了equals和hashcode方法),对Striped.get方法的调用将返回相同的锁/信号量实例。 但是不能保证相反的情况,也就是说,当objectA不等于ObjectB时,我们仍然可以检索相同引用的锁/信号量。 根据针对Striped类的Javadoc,指定更少的条纹会增加为两个不同的键获得相同引用的可能性。

一个例子

让我们基于引言中介绍的场景来看一个非常简单的示例。 我们构造了一个ConcurrentWorker类,在其中我们希望限制对某些资源的并发访问。 但让我们假设有一些不同的资源,因此理想情况下,我们希望限制每个资源的访问,而不仅仅是限制ConcurrentWorker

public class ConcurrentWorker {private Striped<Semaphore> stripedSemaphores = Striped.semaphore(10,3);private Semaphore semaphore = new Semaphore(3);public void stripedConcurrentAccess(String url) throws Exception{Semaphore stripedSemaphore  = stripedSemaphores.get(url);stripedSemaphore.acquire();try{//Access restricted resource hereThread.sleep(25);}finally{stripedSemaphore.release();}}public void nonStripedConcurrentAccess(String url) throws Exception{semaphore.acquire();try{//Access restricted resource hereThread.sleep(25);}finally{semaphore.release();}}
}

在此示例中,我们有两种方法ConcurrentWorker.stripedConcurrentAccessConcurrentWorker.nonStripedConcurrentAccess因此我们可以轻松进行比较。 在这两种情况下,我们都通过调用Thread.sleep 25毫秒来模拟工作。 我们创建了一个Semaphore实例和一个Striped实例,其中包含10个急切创建的,高度引用的Semaphore对象。 在这两种情况下,我们都指定了3个许可,因此任何时候3个线程都可以访问我们的“资源”。 这是一个简单的驱动程序类,用于测量两种方法之间的吞吐量。

public class StripedExampleDriver {private ExecutorService executorService = Executors.newCachedThreadPool();private int numberThreads = 300;private CountDownLatch startSignal = new CountDownLatch(1);private CountDownLatch endSignal = new CountDownLatch(numberThreads);private Stopwatch stopwatch = Stopwatch.createUnstarted();private ConcurrentWorker worker = new ConcurrentWorker();private static final boolean USE_STRIPES = true;private static final boolean NO_STRIPES = false;private static final int POSSIBLE_TASKS_PER_THREAD = 10;private List<String> data = Lists.newArrayList();public static void main(String[] args) throws Exception {StripedExampleDriver driver = new StripedExampleDriver();driver.createData();driver.runStripedExample();driver.reset();driver.runNonStripedExample();driver.shutdown();}private void runStripedExample() throws InterruptedException {runExample(worker, USE_STRIPES, "Striped work");}private void runNonStripedExample() throws InterruptedException {runExample(worker, NO_STRIPES, "Non-Striped work");}private void runExample(final ConcurrentWorker worker, final boolean isStriped, String type) throws InterruptedException {for (int i = 0; i < numberThreads; i++) {final String value = getValue(i % POSSIBLE_TASKS_PER_THREAD);executorService.submit(new Callable<Void>() {@Overridepublic Void call() throws Exception {startSignal.await();if (isStriped) {worker.stripedConcurrentAccess(value);} else {worker.nonStripedConcurrentAccess(value);}endSignal.countDown();return null;}});}stopwatch.start();startSignal.countDown();endSignal.await();stopwatch.stop();System.out.println("Time for" + type + " work [" + stopwatch.elapsed(TimeUnit.MILLISECONDS) + "] millis");}//details left out for clarity

我们使用了300个线程,并分别两次调用了这两个方法,并使用StopWach类记录了时间。

结果

如您所料,条带化版本的性能要好得多。 这是其中一个测试运行的控制台输出:

Time forStriped work work [261] millis
Time forNon-Striped work work [2596] millis

虽然Striped类并不适合所有情况,但当您需要并发不同数据时,它确实很方便。 谢谢你的时间。

资源资源

  • 番石榴API
  • 实践中的并发
  • 这篇文章的源代码

参考: 《 随机编码》博客上的JCG合作伙伴 Bill Bejeck 提供的与Guava Striped Class的细粒度并发。

翻译自: https://www.javacodegeeks.com/2013/09/fine-grained-concurrency-with-the-guava-striped-class.html

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

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

相关文章

iOS-----------关于组件化

打一个比较形象的比喻&#xff0c;把APP比作我们的人体&#xff0c;把胳膊、大腿、心、肝、肺这些人体器官比作组件&#xff0c;各个器官分别负责他们各自的功能&#xff0c;但是他们之间也有主次之分&#xff0c;试想我们的胳膊、大腿等是不能独立完成某个任务的&#xff0c;必…

scrapy 安装

直接命令pip install scrapy安装&#xff0c;提示失败 Failed building wheel for Twisted... Microsoft Visual C 14.0 is required...等等 网上搜索一大摞windows下安装scrapy的资料&#xff0c;实践后终于大功告成&#xff0c;现分享出来 1.首先下载scrapy的whl包&#xff1…

leetcode 罗马数字转整数

罗马数字包含以下七种字符&#xff1a;I&#xff0c;V&#xff0c;X&#xff0c;L&#xff0c;C&#xff0c;D 和M。 字符数值I1V5X10L50C100D500M1000例如&#xff0c; 罗马数字 2 写做II &#xff0c;即为两个并列的 1。12 写做XII &#xff0c;即为 X II 。 27 写做 XXVII, …

android 自定义switch控件,Android中switch自定义样式

android 原生开关按钮控件 Switch 提供样式自定义方式&#xff0c;可供我们修改为适合我们开发使用的样式控件&#xff0c;自定义样式过程如下:自定义switch切换drawable新建swith_thumb.xml文件自定义switch轨道drawable新建switch_track.xmln文件,轨迹如果在选中与否过程并没…

具有瞬态属性的视图对象的钝化和激活

在应用程序模块的钝化/激活周期内&#xff0c;框架也会钝化并激活视图对象。 通常&#xff0c;框架保存有关VO状态&#xff0c;当前行&#xff0c;绑定变量值等的信息。 但是没有数据。 激活视图对象后&#xff0c;将重新执行VO的查询&#xff0c;并重新获取数据。 在大多数情况…

jsonobject修改key的值_JSON字符串操作移除空串更改key/value的介绍

对于JSON字符串的操作。移除键值、添加属性。//删除JSON对象value值var json[.....];delete(json[key]);或者delete(json.key);//添加对象objectjson.objectvalue;或者json[object]value;如果数据是查询数据库得到的&#xff0c;那么可能会存在空值&#xff0c;for循环JSON数据…

pre标签的样式

你可能正在使用 <pre> 标签。这是一个 HTML 中非常特别的标签&#xff0c;它允许其中的空格真正显示出来。例如&#xff1a;四个空格将真实显示成四个空格。这不同于其他标签通常的做法&#xff0c;其他标签会将之间的空白压缩成一个。从这一点来说&#xff0c;<pre&g…

从Hotspot JIT编译器打印生成的汇编代码

有时&#xff0c;在对Java应用程序进行性能分析时&#xff0c;有必要了解Hotspot JIT编译器生成的汇编代码。 这对于确定已做出的优化决策以及我们的代码更改如何影响生成的汇编代码非常有用。 在调试并行算法以确保已按预期应用可见性规则时&#xff0c;知道何时发出什么指令也…

js的闭包

function a(){var n 0;this.inc function () {n; console.log(n);}; } var c new a(); c.inc(); //控制台输出1 c.inc(); //控制台输出2 什么是闭包&#xff1f;这就是闭包&#xff01;&#xff01;有权访问另一个函数作用域内变量的函数都是闭包。当函数可以记住并访…

Background-size完美兼容IE

CSS3 新增的 background-size 是一个很有用的属性&#xff0c;用于定义背景图片的尺寸&#xff0c;有了这个属性&#xff0c;你就可以任意指定背景图片的大小。其中最常用的值应该要数 cover 了&#xff0c;该值能让背景图片缩放至填满整个容器&#xff0c;即使是图片面积小于容…

python第五章上机实践报告_第五章实践报告 - osc_kk5bjg1i的个人空间 - OSCHINA - 中文开源技术交流社区...

1.实践问题&#xff1a;工作分配问题2.问题描述设有n件工作分配给n个人。将工作i分配给第j个人所需的费用为cij 。 设计一个算法&#xff0c;对于给定的工作费用&#xff0c;为每一个人都分配1 件不同的工作&#xff0c;并使总费用达到最小。输入格式:输入数据的第一行有1 个正…

android服务下载,android服务之bindService和unService中下载任务中的应用

通过bindService方法来调用服务final Down down data;viewHolder.videoActionBtn.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View v) {if(bEditMode) {// 处于编辑模式&#xff0c;点击删除deleteDown(down);} else {// 处于播放模式&…

02CSS文本样式08

day08 CSS文本样式   font-family设置字体   font-size文字大小   font-size绝对单位|相对单位   cm mm pt pc xx-small   x-small medium large small xx-large x-large   相对单位&#xff1a;px em % larger smaller   color文字颜色   color:颜色|十六进制…

Illustrator、Indesign与Photoshop

Adobe illustrator是一种应用于出版、多媒体和在线图像的工业标准矢量插画的软件&#xff0c;作为一款非常好的图片处理工具&#xff0c;Adobe Illustrator广泛应用于印刷出版、海报书籍排版、专业插画、多媒体图像处理和互联网页面的制作等&#xff0c;也可以为线稿提供较高的…

判断sem信号量为零_将信号量递减为零的进程崩溃时,如何恢复信号量?

我有多个使用g 编译的应用程序&#xff0c;它们在Ubuntu中运行。我正在使用命名信号量来协调不同进程之间的关系。除非 出现以下情况&#xff0c; 否则所有方法都可以正常工作&#xff1a;如果其中一个进程调用sem_wait()或sem_timedwait()使信号量递减&#xff0c;然后在有机会…

在Spring中使用Future对象调用Async方法调用

下一个示例将演示Spring容器内部的异步方法调用。 为什么我们需要异步方法调用&#xff1f; 在某些情况下&#xff0c;我们并不真正知道是否需要重播或何时应返回结果。 传统方式在Java EE的异步处理世界中&#xff0c;使用队列/主题。 我们可以在Spring中进行相同的操作&#…

select里加链接

html select标签加链接的方法有很多&#xff0c;接下来为大家介绍下几个比较经典的&#xff0c;,感兴趣的朋友可以参考下哈&#xff0c;希望可以帮助到你 第一种 &#xff1a; <SCRIPT languagejavascript> <!-- // open the related site windows function mbar…

android ipc 多个客户端,Android IPC之AIDL进阶篇

前言在Android IPC之AIDL中我介绍了如何使用AIDL进行多进程通信&#xff0c;不过由于当时个人水平有限&#xff0c;仅仅介绍了最基础的部分&#xff0c;所以本篇博客主要是在Android IPC之AIDL的基础上深入介绍下AIDL的进阶的几点理解以及用法。AIDL接口中的in out inout的含义…

mysql数据库(3)-查询

数据库设计规范 58到家数据库30条军规解读查询 创建数据库、数据表 -- 创建数据库 create database python_test_1 charsetutf8; -- 使用数据库 use python_test_1; -- students表 create table students( id int unsigned primary key auto_increment not null, name varchar(…

Spring Data Solr教程:向所有存储库添加自定义方法

如果我们在现实生活中的软件项目中使用Spring Data Solr&#xff0c;很可能我们迟早会遇到一个要求&#xff0c;该要求指出我们的应用程序必须能够与本地Solr服务器和SolrCloud进行通信 。 目前&#xff0c;满足此要求意味着我们必须向所有Spring Data Solr存储库添加自定义方法…