我们可以打开任意Files.newByteChannel(path)
简单的信道,并且会很好地工作。问题是,如果我想开一个以上的频道:
Channel chan1 = Files.newByteChannel(path);
Channel chan2 = Files.newByteChannel(path);
上面的例子,一般也不会很好地工作。考虑情况:
Channel chan1 = Files.newByteChannel(path); //OK
//Some other process moved path and created an new file with the path
Channel chan2 = Files.newByteChannel(path); //Damn!
发生的竞争状态。在linux中,我们有dup
样的系统调用以及fcntl(F_DUPFD, int)
int fd == open(path);
int duplicated = fcntl(fd, F_DUPFD, fd);
并应工作。
有没有办法做到这一点在Java中,避免写JNI
功能?
UPD:我想重复的原因是,我想将数据从一个文件同时发送给多个SocketChannel
s。因此,它似乎是合理的有一个单独的FileChannel
转移到一个单一的SocketChannel
。
Java有重复FileChannels没有公共API。
然而,没有必要重复FileChannel的同时写入多个SocketChannels。
FileChannel.transferTo
可以同时在多个线程中(至少在类似Unix的系统)一起使用。正如Javadoc中说,这种方法不会修改通道的位置。FileChannel.read(ByteBuffer, long)
也可以在Unix上同时使用。在Windows中,这个方法保持通道的位置锁定。FileChannel.map
的多个字节缓冲区的意见。这些MappedByteBuffers可以同时使用。如果你仍然想从Java(虽然我不建议这样做)调用dup
,你可以使用反射滥用私有API:
int sun.nio.fs.UnixNativeDispatcher.dup(int fd)
是在Unix dup
直接Java包装;long sun.nio.ch.FileDispatcherImpl.duplicateHandle(long handle)
是Java包装在Windows DuplicateHandle
。