多线程环境中的Java CRC32计算

蝶形

我有以下util类用于crc32计算:

import java.util.zip.CRC32;
import java.util.zip.Checksum;

public class StringUtils {

    public static long crc32(String input) {
        byte[] bytes = input.getBytes();
        Checksum checksum = new CRC32();
        checksum.update(bytes, 0, bytes.length);

        return checksum.getValue();
    }

}

表现对我来说是非常重要的标准。

现在,我正在考虑对该方法进行可能的重构,并且正在考虑将checksum其作为静态字段移到类级别上,如下所示:

public class StringUtils {

    public static Checksum checksum = new CRC32();

    public static long crc32(String input) {
        byte[] bytes = input.getBytes();
        checksum.update(bytes, 0, bytes.length);

        return checksum.getValue();
    }

}

但我不确定它是否可以在并发多线程环境中正常工作。请告知-这种重构是个好主意。

大卫·埃尔曼(David Ehrmann)

就像其他人所说的那样,CRC32不是线程安全的,因此您必须同步或使用ThreadLocal,但是它们并不是特别有帮助。

如果您看一下CRC32的实现,则是一个字段。在执行任何操作之前,请对代码进行基准测试。在Java的复杂GC,JIT和转义分析之间,很难预测您是否会看到任何好处。

重写此代码以避免数组分配可能会给您带来更大的好处:

byte[] bytes = input.getBytes();

编辑:除非绝对必要,否则请不要这样做。

这会展开String的内部getBytes()以避免某些中间缓冲,并利用CRC32对直接字节缓冲区进行了优化的优势:

public class StringUtils {
    private static final ThreadLocal<ByteBuffer> BUFFER = ThreadLocal.withInitial(() -> ByteBuffer.allocateDirect(4094));

    public static long crc32(String input) {
        CharBuffer inputBuffer = CharBuffer.wrap(input);
        ByteBuffer buffer = BUFFER.get();
        CRC32 crc32 = new CRC32();
        CharsetEncoder encoder = Charset.defaultCharset().newEncoder();

        CoderResult coderResult;
        do {
            try {
                coderResult = encoder.encode(inputBuffer, buffer, true);
                buffer.flip();
                crc32.update(buffer);
            } finally {
                buffer.reset();
            }
        } while (coderResult.isOverflow());

        return crc32.getValue();
    }
}

通过手动进行编码(对于ASCII而言这是微不足道的),您甚至可以做得更好。使性能复杂化的是平衡将字节复制到缓冲区中,以通过对实际CRC32实现的JNI调用读出字节。实际上,由于JNI开销,中间缓冲区可能会更快。在执行此操作之前,请确保先读取直接字节缓冲区如果您实际上并没有重用缓冲区,则速度可能会很慢。

当您真正了解正在发生的事情时,您会发现这getBytes()比您想像的要复杂得多,并且担心分配一个琐碎的,短暂的CRC32对象并不是对性能的主要贡献。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章