Java8内置了强大的多核支持,我们在处理数据的时候,如果不充分利用多核,都好不意思跟老板打招呼。
我们经常会使用AtomicInteger来做计数器,如下所示:
List<String> words = Files.readAllLines(Paths.get("src/main/resources/dic.txt")); AtomicInteger i = new AtomicInteger(); words.parallelStream().forEach(word -> { //获取word的同义词、反义词以及相关词 //...... LOGGER.info("进度:" + total + "/" + i.incrementAndGet() + " 来自线程:" + Thread.currentThread()); });
在这段代码中,我们需要注意两点,一是parallelStream,二是变量i。
parallelStream的使用表示forEach中的代码段有可能会在不同线程中并发执行,因此变量i的incrementAndGet方法要保证是原子操作,否则计数器的数据就可能会出错。
没啥问题,一切都还很美好,so far so nice。
有一天,我们的需求复杂了,我们需要的计数器不仅仅只是+1,而是要支持小数,如2.5,3.1等等,这有什么大不了的,我们把AtomicInteger换成AtomicFloat不就支持小数了吗?
接着我们翻遍了JDK类库,都没有找到AtomicFloat,怎么回事呢?
最后终于在java.util.concurrent.atomic的package-summary.html页面的最后部分发现了秘密:
Additionally, classes are provided only for those types that are commonly useful in intended applications. For example, there is no atomic class for representing byte
. In those infrequent cases where you would like to do so, you can use an AtomicInteger
to hold byte
values, and cast appropriately. You can also hold floats using Float.floatToRawIntBits(float)
andFloat.intBitsToFloat(int)
conversions, and doubles using Double.doubleToRawLongBits(double)
andDouble.longBitsToDouble(long)
conversions.
接下来我们就可以利用AtomicInteger作为基础来实现自己的AtomicFloat了,实现AtomicDouble和AtomicByte也是类似的做法,下面看看在word分词中实现的AtomicFloat:
package org.apdplat.word.util; import java.util.concurrent.atomic.AtomicInteger; /** * 因为Java没有提供AtomicFloat * 所以自己实现一个 * @author 杨尚川 */ public class AtomicFloat extends Number { private AtomicInteger bits; public AtomicFloat() { this(0f); } public AtomicFloat(float initialValue) { bits = new AtomicInteger(Float.floatToIntBits(initialValue)); } public final float addAndGet(float delta){ float expect; float update; do { expect = get(); update = expect + delta; } while(!this.compareAndSet(expect, update)); return update; } public final float getAndAdd(float delta){ float expect; float update; do { expect = get(); update = expect + delta; } while(!this.compareAndSet(expect, update)); return expect; } public final float getAndDecrement(){ return getAndAdd(-1); } public final float decrementAndGet(){ return addAndGet(-1); } public final float getAndIncrement(){ return getAndAdd(1); } public final float incrementAndGet(){ return addAndGet(1); } public final float getAndSet(float newValue) { float expect; do { expect = get(); } while(!this.compareAndSet(expect, newValue)); return expect; } public final boolean compareAndSet(float expect, float update) { return bits.compareAndSet(Float.floatToIntBits(expect), Float.floatToIntBits(update)); } public final void set(float newValue) { bits.set(Float.floatToIntBits(newValue)); } public final float get() { return Float.intBitsToFloat(bits.get()); } public float floatValue() { return get(); } public double doubleValue() { return (double) floatValue(); } public int intValue() { return (int) get(); } public long longValue() { return (long) get(); } public String toString() { return Float.toString(get()); } }
类似的情况也发生在了FloatStream身上,我们在JDK类库中也找不到FloatStream,看下面这段描述:
There are primitive-specialized versions of Stream for ints, longs, and doubles: IntStream, LongStream, DoubleStream. There are not primitive versions for the rest of the primitive types because it would have required an unacceptable amount of bloat in the JDK. IntStream, LongStream, and DoubleStream were deemed useful enough to include, and streams of other numeric primitives can represented using these three via widening primitive conversion.
相关推荐
配置JDK环境,处理windows下存在多种JDK版本情况下,如何进行完美的在多个JDK版本的切换
向 JDK 添加提供程序以支持 GMSSL。BGMProvider目标是提供一个完整的GMTLS JAVA实现。BGMProvider 基于 Java Cryptography Architecture(JCA) 框架, 提供一个JCE provider 和 JSSE provider。
JDK11安装包,JDK11安装包JDK11安装包,JDK11安装包JDK11安装包,JDK11安装包JDK11安装包,JDK11安装包JDK11安装包,JDK11安装包JDK11安装包,JDK11安装包JDK11安装包,JDK11安装包JDK11安装包,JDK11安装包JDK11...
jdk8帮助文档jdk8帮助文档jdk8帮助文档jdk8帮助文档jdk8帮助文档jdk8帮助文档jdk8帮助文档jdk8帮助文档jdk8帮助文档jdk8帮助文档jdk8帮助文档jdk8帮助文档jdk8帮助文档jdk8帮助文档jdk8帮助文档jdk8帮助文档jdk8帮助...
mac系统jdk1.8安装包!mac系统jdk1.8安装包!mac系统jdk1.8安装包!mac系统jdk1.8安装包!mac系统jdk1.8安装包!mac系统jdk1.8安装包!mac系统jdk1.8安装包!mac系统jdk1.8安装包!mac系统jdk1.8安装包!mac系统jdk...
jdk7 jdk8 jdk9 jdk10 jdk11 jdk12 jdk13 jdk14 (win-64位) 资源共享
JDK大全 JDK1.6 JDK1.7 JDK1.8 JDK1.9 JDK10 JDK11 JDK12
jdk内存设置 jdk内存设置 jdk内存设置 jdk内存设置 jdk内存设置 jdk内存设置
JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK11、JDK...
jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk配置jdk...
在以前的jdk版本中,只要安装jdk文件就会在本地自动生成jdk和jre两个文件,但是在新的jdk版本中没有自动生成jre文件,也没有tools.jar包。没办法就下载放进去了,不知道有没有其他的办法解决这个问题。
安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装JDK安装...
官网 jdk6,jdk7,jdk8,jdk9,jdk10 windox 32位、64位、linux 32位、64位 百度云。
Jdk的Timer 实现定时器,本例代码包括Handler 发送消息的简单实现过程 定时器 Timer,在这里演示一个进度条不断更新
Jdk15泛型的实现
如果已经安装过JDK,不小心被手工删除了部份文件,比如将d:\java\jdk目录下的文件手工删除了,可能再执行installjdk.bat由于没有卸载干净,即使用360也可能卸载不干净,可以使用“强力删除软件”这个目录中的带的...
Linux更换JDK+weblogic更换JDK 全局更换JDK Linux更换JDK+weblogic更换JDK 全局更换JDK
jdk17和jdk1.8下载安装包
java-jdk1.8-8u361-all-jdk-win-linux 该压缩包中包含jdk1.8-8u361下windows版本和linux版本,其包含快速安装包和对应的jdk压缩包版本,具体内容如下: jdk-8u361-linux-aarch64.rpm jdk-8u361-linux-i586.rpm jdk-8...
jdk-11.0.6_windowsjdk-11.0.6_windowsjdk-11.0.6_windowsjdk-11.0.6_windowsjdk-11.0.6_windowsjdk-11.0.6_windowsjdk-11.0.6_windows