我最近遇到了这个 article,它为内存映射文件提供了一个很好的介绍,以及它如何在两个进程之间共享.以下是读入文件的进程的代码:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

public class MemoryMapReader {

 /**
  * @param args
  * @throws IOException 
  * @throws FileNotFoundException 
  * @throws InterruptedException 
  */
 public static void main(String[] args) throws FileNotFoundException,IOException,InterruptedException {

  FileChannel fc = new RandomAccessFile(new File("c:/tmp/mapped.txt"),"rw").getChannel();

  long bufferSize=8*1000;
  MappedByteBuffer mem = fc.map(FileChannel.MapMode.READ_ONLY,bufferSize);
  long oldSize=fc.size();

  long currentPos = 0;
  long xx=currentPos;

  long startTime = System.currentTimeMillis();
  long lastValue=-1;
  for(;;)
  {

   while(mem.hasRemaining())
   {
    lastValue=mem.getLong();
    currentPos +=8;
   }
   if(currentPos < oldSize)
   {

    xx = xx + mem.position();
    mem = fc.map(FileChannel.MapMode.READ_ONLY,xx,bufferSize);
    continue;   
   }
   else
   {
     long end = System.currentTimeMillis();
     long tot = end-startTime;
     System.out.println(String.format("Last Value Read %s,Time(ms) %s ",lastValue,tot));
     System.out.println("Waiting for message");
     while(true)
     {
      long newSize=fc.size();
      if(newSize>oldSize)
      {
       oldSize = newSize;
       xx = xx + mem.position();
       mem = fc.map(FileChannel.MapMode.READ_ONLY,oldSize-xx);
       System.out.println("Got some data");
       break;
      }
     }   
   }

  }

 }

}

但是,我对这种方法提出了一些意见/问题:

如果我们只在空文件上执行阅读器,即运行

long bufferSize=8*1000;
  MappedByteBuffer mem = fc.map(FileChannel.MapMode.READ_ONLY,bufferSize);
  long oldSize=fc.size();

这将分配8000个字节,现在将扩展该文件.返回的缓冲区的限制为8000,位置为0,因此,读者可以继续读取空数据.发生这种情况后,读者将停止,因为currentPos == oldSize.

据说现在编写进来(代码被省略,因为大部分内容都很简单,可以从网站上引用) – 它使用相同的缓冲区大小,因此它将首先写入8000个字节,然后分配另外8000个,扩展文件.现在,如果我们假设这个过程暂停,然后我们回到阅读器,那么读者会看到文件的新大小并分配剩余部分(从位置8000到1600)并再次开始阅读,阅读另一个垃圾…

我是否有同步这两个操作的原因有点困惑.据我所知,任何对map的调用都可能会扩展文件,实际上是一个空缓冲区(用零填充)或者编写器可能刚刚扩展了文件,但还没有写入任何东西……

解决方法

有几种方法.

>让作者获得尚未编写的区域的独家锁定.在写完所有内容后释放锁定.这与在该系统上运行的每个其他应用程序兼容,但它要求读者足够聪明以重试失败的读取,除非您将其与其他方法之一结合使用
>使用另一个通信渠道,例如管道或套接字或文件的元数据通道,让作者告诉读者完成的写入.
>在文件中的一个位置写一个特殊的标记(作为协议的一部分),告诉写入的数据,例如

MappedByteBuffer bb;
…
// write your data

bb.force();// ensure completion of all writes
bb.put(specialPosition,specialMarkerValue);
bb.force();// ensure visibility of the marker

Java NIO – 内存映射文件的更多相关文章

  1. Java NIO与IO的区别以及比较

    这篇文章主要介绍了Java NIO与IO的区别以及比较,文章通过围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下

  2. Java使用NIO优化IO实现文件上传下载功能

    IO 是基于流来读取的,而NIO则是基于块读取,面向流 的 I/O 系统一次一个字节地处理数据,这篇文章主要介绍了Java使用NIO优化IO实现文件上传下载功能,需要的朋友可以参考下

  3. Netty与NIO超详细讲解

    Netty本质上是一个NIO的框架,适用于服务器通讯相关的多种应用场景。底层是NIO,NIO底层是Java IO和网络IO,再往下是TCP/IP协议,下面我们跟随文章来详细了解

  4. Windows内存映射文件

    我试图调查Windows内核关于内存映射文件/虚拟内存的行为.具体来说,我感兴趣的是确定将内存映射文件的内容(通过Windows)刷新到磁盘的频率以及Windows使用什么标准来决定它是时候这样做了.我在网上做了一些研究,除了MSDN更多地处理’howsandwhys’而不是详细说明内部工作之外,似乎没有太多的信息.如果有人能指出我的任何文章,或者之前已经研究过并有一些见解我会欢迎它.谢谢.内存映

  5. windows – 使用内存映射文件读取大文件

    我看到许多文章建议不要将大文件映射为mmap文件,因此虚拟地址空间不会仅由mmap完成.在地址空间急剧增加的64位进程中,这会如何变化?如果我需要随机访问文件,是否有理由不立即映射整个文件?

  6. windows-server-2012 – Jenkins Slave在构建期间脱机

    在WindowsServer2012上安装了Jenkins1.651主服务器和从服务器.slave专门用于运行Selenium测试,但大部分时间它都处于脱机状态:和奴隶日志:造成这个问题的原因是什么以及如何解决?

  7. Windows – 文件的内存映射与CreateFile / ReadFile [已关闭]

    使用内存映射文件读取使用CreateFileReadFile组合执行相同操作有什么缺点(如果有)?

  8. windows – 什么会导致部分句柄泄漏?

    这是mypreviousquestion.的后续问题正如thisanswertomypreviousquestion中所建议的那样,我使用ProcessExplorer来分析我的应用程序用来查找句柄泄漏的句柄列表.泄漏的句柄属于Section类型.什么是一个部分句柄,它在哪里使用以及什么可能导致部分句柄泄漏?我没有在我的代码中使用内存映射文件.引用MarkRussinovich的InsideWin

  9. 我们需要有关使用Java NIO的服务器软件实现的建议

    我正在尝试计算我必须构建的服务器上的负载.我需要创建一个服务器,在sql数据库中注册了一百万用户.在一周内,每个用户将大约连接3-4次.每次用户启动并下载1-30MB数据时,可能需要1-2分钟.上传完成后,将在几分钟内删除.我知道如何制作和查询sql数据库,但在这种情况下要考虑什么?解决方法我正在使用Netty来实现类似的方案.它只是工作!

  10. java.nio对Web服务器有什么好处?

    为什么这样更好?更糟糕的是:即使聊天服务器上根本没有任何活动,也没有发送任何消息,客户端仍然会浪费那些2GB.添加大量的上下文切换,您会发现问题.在这种情况下,你最好使用非阻塞NIO,其中较少的线程(最终只有1!

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部