java bytebuffer cpu 100%_java – 多线程ByteBuffers比顺序慢?

我有一个需要处理的巨大字节数组.从理论上讲,应该可以将工作分成均匀的部分,并将它们分配给不同的线程,以提高多核机器的性能.

我为每个线程分配了一个ByteBuffer,并分别处理了部分数据.即使我有8个逻辑处理器,最终性能也比单个线程慢.它也是非常不一致的.有时相同的输入是加倍或更多的两倍.这是为什么?数据首先加载到内存中,因此不再执行IO操作.

public ByteBuffer getByteBuffer() throws IOException

{

File binaryFile = new File("...");

FileChannel binaryFileChannel = new RandomAccessFile(binaryFile, "r").getChannel();

return binaryFileChannel.map(FileChannel.MapMode.READ_ONLY, 0, binaryFileChannel.size());

}

我使用Executors进行并发处理:

int threadsCount = Runtime.getRuntime().availableProcessors();

ExecutorService executorService = Executors.newFixedThreadPool(threadsCount);

ExecutorCompletionService completionService = new ExecutorCompletionService<>(executorService);

for (ByteBufferRange byteBufferRange : byteBufferRanges)

{

Callable task = () ->

{

performTask(byteBufferRange);

return null;

};

completionService.submit(task);

}

// Wait for all tasks to finish

for (ByteBufferRange ignored : byteBufferRanges)

{

completionService.take().get();

}

executorService.shutdown();

并发任务performTask()使用自己的ByteBuffer实例从缓冲区读取内存,进行计算等.它们不会彼此同步,写入或影响.什么是错误的想法或者这不是并行化的好例子?

ByteBuffer.wrap()和MappedByteBuffer都存在同样的问题.

最佳答案 正如@EJP所提到的,虽然SSD可能有所帮助,但磁盘并不是真正的多线程.映射缓冲区的目的是让您不必自己管理内存;让操作系统做到这一点,因为它的虚拟内存管理器和文件系统缓存比将其移入Java堆更快,并且可能比你编写的任何内存管理代码更快.

如果处理真的可以并行化,那么最好让单个线程读取整个文件,将其分成块(可能是某些中间数据格式),然后让执行程序在这些块上工作.文件读取线程可以与其他线程并发运行,因此您无需读取整个文件即可开始处理.

您可能想尝试将执行程序的数量设置为核心 – 1,这样您就不会使文件读取线程饿死.这将使操作系统有机会在没有上下文切换的情况下保持文件读取线程在单个内核上运行,因此在使用其他内核进行CPU密集型工作时,您将获得良好的IO性能.

仅供参考,这就是Apache Spark的基础.如果您需要处理更大的文件或者需要比单个系统更快地处理,您可能需要查看它.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值