我们可以打开一个简单的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
。因此,将单独的FileChannel
转移到单个SocketChannel
似乎是合理的。
答案 0 :(得分:2)
Java没有用于复制FileChannel的公共API。
但是,无需复制FileChannel即可同时写入多个SocketChannel。
FileChannel.transferTo
可以在多个线程中同时使用(至少在类似Unix的系统上)。如Javadoc所说,此方法不会修改频道的位置。FileChannel.read(ByteBuffer, long)
也可以在Unix上同时使用。在Windows上,此方法可保存频道的位置锁定。FileChannel.map
创建同一FileChannel的多个ByteBuffer视图。这些MappedByteBuffer可以同时使用。如果您仍想从Java调用dup
(尽管我不建议这样做),则可以使用Reflection使用私有API:
int sun.nio.fs.UnixNativeDispatcher.dup(int fd)
是Unix上dup
的直接Java包装器; long sun.nio.ch.FileDispatcherImpl.duplicateHandle(long handle)
是Windows上DuplicateHandle
的Java包装器。