[转载]Java8并发教程-Atomic variables and ConcurrencyMap

原文:Java8并发教程-Atomic variables and ConcurrencyMap

这是本教程的最后一篇.我们还是用到了上一篇中提到的那个工具类和其中的两个方法.请看上篇文章,来获取此代码.

1 AutomicInteger

java.concurrent.atomic包中,提供了大量的有用的类,来执行原子性的操作.原子性的意思是,所有的操作要不就都执行成功,要不就都不执行成功.

这些原子性的类内部,都使用了著名的CAS指令.现代处理器都支持这条指令.相对于使用锁的synchronized关键字来说,这条指令操作起来更快.所以,如果我们只想并发的对一个共享变量进行操作,那使用这些原子性的类,更为方便和快捷.

我们首先看一下AutomicInteger这个类如何使用:

image.png

通过使用AutomicInteger类型,而不是Integer类型,我们能够以线程安全的方式,来并发的修改一个数值.而不需要跟以前一样,使用synchronized关键字或者显式锁.AutomicInteger类型提供的incrementAndGet()方法,是线程安全的,所以我们可以放心的在多个线程中使用这个方法,而不需要担心那些预料之外的事情发生.

AutomicInteger类型还提供了很多其他的原子性的方法.其中updateAndGet()方法允许我们传入一个lambda表达式,来对此数值就行操作.

image

accumulateAndGet()方法,接受一种IntBinaryOperator类型的lambda表达式.在下面这个例子中,我们使用这个方法,来并发的计算0到1000的和.

image

java.concurrent.atomic包中,还提供了很多其他的原子类.如AutomicBoolean, AutomicLong, AutomicReference等.

2 LongAddr

LongAddrAtomicLong相似,用于连续的为数值增加一个值.

image.png

** LongAddr还提供了其他的原子性的,线程安全的函数,比如 add(),和 increment().但是,这些方法并不只是单纯的计算一个结果,它还在内部维护了很多变量,用于减少线程之间的冲突.我们可以通过 sum()方法和 sumThenRest()**方法,来获取计算的结果.

这个类,在执行写操作的线程多于执行读操作的线程这种情景中,比较常用.通常用在那些需要获取统计数据的情况中.比如,你想要计算服务器接受的请求数.** LongAddr**的缺点是,由于要在内存中维护大量的变量,所以它比较耗内存.

3 LongAccumulator

LongAccumulator和 LongAddr相似,但是更加常用.它执行的不是简单的操作,它接受的是 LongBinaryOperator类型的lambda表达式.如下例所示:

image.png

我们通过函数2 * x + y和初始值1,创建了一个LongAccumulator.每次调用accumulate(i)函数,当前值会作为lambda表达式的x值, i会作为lambda表达式的y值,传递到lambda表达式中.

LongAccumulator就像LongAddr一样,内部也维护了大量的变量,来减少线程之间的冲突.

4 ConcurrentMap

ConcurrentMap接口,扩充了Map接口,成为了并发编程中,最有用的一个接口.

我们想创建一个包含四对数据的CouncurrentMap.在后面我们将用它来实验那些函数.

image.png

forEach()方法接受一个类型为BiConsumer的lambda表达式作为参数,其中此lambda表达式的参数为map中的键值对.我们可以用forEach()这个方法来在当前线程内,串行的迭代这个map.

image.png

putIfAbsent()方法,会在给定的key没有value时,为其添加一个value.至少在ConcurrentHashMap中,其实现是线程安全的.

image.png

getOrDefault()方法,会尝试获取给定key的value,如果不存在,则返回我们指定的默认值.

image.png

replaceAll()方法,用于替换此Map中,满足条件的项的value.

image.png

compute()方法,允许我们对特定的项进行转换.

image.png

除了compute()方法,还有两个变体,computeIfAbsent()computeIfPresent(),分别在给定的key不存在时和存在时进行操作.

merge()方法,用于对给定key的value进行操作,生成一个新的值.

image.png

5 ConcurrentHashMap

上面介绍的函数,都是ConcurrentMap这个接口提供的.这些函数可以被任何实现了ConcurrentMap的类使用.除此之外,ConcurrentHashMap还提供了很多其他用于并发操作的函数.

就像parallel streams一样,这些函数内部都使用ForkJoinPool,在Java8中,我们可以通过ForkJoinPool.commonPool()函数来获得一个ForkJoinPool.这个线程池,默认可以使用的线程数,取决于你的机器上的CPU上,有几个核心.在我的四核的机器上,其为3.

image.png

我们可以通过设置JVM的参数,来修改这个数值.

image.png

我们还是使用上面的那个包含四条数据的map.但是这里我们不使用ConcurrentMap这个接口了,而是使用ConcurrentHashMap这个具体实现类,来使用ConcurrentHashMap中特有的函数.

image.png

Java8中,提供了三种并行操作的函数:forEach(), search()reduce().这些函数的第一个参数,都是如果要启动并发执行的话,Collection的最小阈值.比如,如果我们设置了这个阈值为500,而map的大小为499,那就会在一个线程中,串行的执行.而如果map的大小大于500,就会开启多个线程,并行的执行.在后面的例子中,我们将这个阈值设置为1,这就意味着,总是并行的执行操作.

6 ForEach

forEach()方法,用于并行的执行迭代map中的key/value对的操作.因为在我的机器上,ForkJoinPool的最大尺寸为3,所以在下面的例子中,你会看到,最多启动了三个线程.

image.png

7 Search

search()函数用于并行的查找map中给定的key的值,如果找到,就返回其value,如果找不到,就返回null.如果会找到多个,则其返回值不确定.也要注意,ConcurrentHashMap中的元素是无序的.

image.png

还有一个只用于搜索map的value的方法,如下图所示:

image.png

8 Reduce

reduce()函数,接受两个类型为BigFunction的lambda表达式.第一个lambda表达式,会将map中的每一个key/value对转换成一个值,然后第二个lambda表达式,会将这些转换后的值,拼接成一个单一的结果.它会忽略null.

image.png

作者:AlstonWilliams
链接:https://www.jianshu.com/p/6326c80f7a41
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容