`

实现JDK没有提供的AtomicFloat

阅读更多

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.

 

 

 

 

 

 

 

1
0
分享到:
评论
1 楼 戢_时光 2015-05-22  

相关推荐

    BGMProvider目标是提供一个完整的GMTLS JAVA实现 向 JDK 添加提供程序以支持 GMSSL

    向 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安装包,JDK11安装包JDK11...

    Windows上实现jdk和Mysql(含数据)整体环境和配置以及数据迁移复用(Bat中实现jdkmysql环境变量配置修改my

    Windows上实现jdk和Mysql(含数据)整体环境和配置以及数据迁移复用(Bat中实现jdkmysql环境变量配置修改my.ini文件路径以及安装mysql服务)资源合集 博客地址: ...前后端分离的系统,需要部署在windows服务器上,若后期...

    jdk8帮助文档 jdk8帮助文档jdk8帮助文档

    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系

    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...

    jdk8、jdk11、jdk17版本下载

    Java Development Kit(JDK)是Java编程语言的核心组件,提供了编写、编译、调试和运行Java应用程序所需的所有工具。在本文中,我们将深入探讨JDK的三个重要版本:JDK 8、JDK 11和JDK 17,它们都被视为长期支持(LTS...

    JDK7安装包.zip

    JDK7安装包.zip\JDK7安装包.zip\JDK7安装包.zip\JDK7安装包.zip\JDK7安装包.zip JDK7安装包.zip\JDK7安装包.zip\JDK7安装包.zip\JDK7安装包.zip\JDK7安装包.zip JDK7安装包.zip\JDK7安装包.zip\JDK7安装包.zip\JDK7...

    jdk7 jdk8 jdk9 jdk10 jdk11 jdk12 jdk13 jdk14 (win-64位) 百度网盘下载

    jdk7 jdk8 jdk9 jdk10 jdk11 jdk12 jdk13 jdk14 (win-64位) 资源共享

    jdk7 jdk8 jdk9 jdk10 jdk11 jdk12 jdk13 jdk14 (linux-rpm 64位) 百度网盘下载

    jdk7 jdk8 jdk9 jdk10 jdk11 jdk12 jdk13 jdk14 (linux-rpm 64位) 资源共享

    jdk1.6 和jdk1.8

    其次,新的Stream API为处理集合数据提供了便利,通过链式操作实现过滤、映射和聚合等操作。再者,日期和时间API的重大改革,带来了java.time包,提供了更直观且易于使用的日期和时间处理类。此外,方法引用来替代...

    JDK资源包合集(JDK6+JDK7+JDK8)

    同时,为了在不同的项目中切换不同版本的JDK,可以利用工具如JEnv或手动调整系统路径来实现。 总结这三个版本,JDK6奠定了现代Java的基础,JDK7带来了语言层面的改进,而JDK8则引领了Java向函数式编程的转变。这些...

    jdk1.8-src

    Stream API是JDK1.8中的一大亮点,提供了对数据集合的高效、声明式处理方式。Stream可以看作是从数据源(如集合、数组)生成的一系列元素序列,支持并行和串行操作。例如,`list.stream().filter(x -&gt; x &gt; 10).map(x...

    jdk-11.0.4-64bit.zip jdk-11版本

    jdk-11版本安装包、jdk-11版本安装包、jdk-11版本安装包 jdk-11版本安装包、jdk-11版本安装包、jdk-11版本安装包 jdk-11版本安装包、jdk-11版本安装包、jdk-11版本安装包 jdk-11版本安装包、jdk-11版本安装包、jdk-...

    JDK- jdk1.8.0-211.zip

    JDK 8包含了Nashorn JavaScript引擎,允许Java代码与JavaScript代码交互,实现Java与JavaScript的无缝融合,提供了JSR 223脚本接口的实现。 ### 9. **并发和性能优化** JDK 8对并发库进行了优化,包括改进的Fork/...

    包含 jdk1.5免安装、jdk1.6免安装、jdk1.8(32和64)

    Java Development Kit (JDK) 是Java编程语言的核心组件,它为开发者提供了编译、调试和运行Java应用程序所需的所有工具。这个压缩包包含了三个不同版本的JDK:JDK 1.5、JDK 1.6和JDK 1.8,其中1.5和1.6是早期版本,...

    Windows JDK安装,包含 jdk8 jdk11 jdk17 jdk22

    Windows JDK安装 包含 jdk8 jdk11 jdk17 jdk22 x64位安装包

    旧版本JDK JDK1.4

    **Java Development Kit (JDK) 1.4:历史、特性与重要性** JDK(Java Development Kit)是Oracle公司发布的用于开发Java应用程序的软件开发工具包,它包含了编译器、调试器、文档和Java运行环境等必要组件。JDK 1.4...

    windows64位jdk6、jdk7、jdk8安装包

    Java开发工具包(Java Development Kit,简称JDK)是Oracle公司提供的用于开发和运行Java应用程序的软件包。在本主题中,我们重点关注的是Windows 64位系统下的JDK6、JDK7和JDK8的安装包。这三个版本的JDK在Java的...

    JDK17安装包和文档

    在Java编程领域,JDK(Java Development Kit)是开发者不可或缺的基础工具,它提供了编译、运行和调试Java应用程序所需的所有组件。JDK17,作为Java的一个重要版本,引入了许多新特性、增强功能以及性能优化,旨在...

Global site tag (gtag.js) - Google Analytics