java - Java中RandomAccessFile的并发

标签 java multithreading randomaccessfile filechannel

我正在创建一个 RandomAccessFile 对象以通过多个线程写入文件(在 SSD 上)。每个线程都尝试在文件中的特定位置写入直接字节缓冲区,我确保线程写入的位置不会与另一个线程重叠:

file_.getChannel().write(buffer, position);

其中 file_RandomAccessFile 的实例,buffer 是直接字节缓冲区。

对于 RandomAccessFile 对象,由于我没有使用 fallocate 分配文件,并且文件的长度在变化,这是否会利用底层媒体的并发性?

如果不是,在创建文件时不调用 fallocate 使用上述函数是否有意义?

最佳答案

我用下面的代码做了一些测试:

   public class App {
    public static CountDownLatch latch;

    public static void main(String[] args) throws InterruptedException, IOException {
        File f = new File("test.txt");
        RandomAccessFile file = new RandomAccessFile("test.txt", "rw");
        latch = new CountDownLatch(5);
        for (int i = 0; i < 5; i++) {
            Thread t = new Thread(new WritingThread(i, (long) i * 10, file.getChannel()));
            t.start();

        }
        latch.await();
        file.close();
        InputStream fileR = new FileInputStream("test.txt");
        byte[] bytes = IOUtils.toByteArray(fileR);
        for (int i = 0; i < bytes.length; i++) {
            System.out.println(bytes[i]);

        }  
    }

    public static class WritingThread implements Runnable {
        private long startPosition = 0;
        private FileChannel channel;
        private int id;

        public WritingThread(int id, long startPosition, FileChannel channel) {
            super();
            this.startPosition = startPosition;
            this.channel = channel;
            this.id = id;

        }

        private ByteBuffer generateStaticBytes() {
            ByteBuffer buf = ByteBuffer.allocate(10);
            byte[] b = new byte[10];
            for (int i = 0; i < 10; i++) {
                b[i] = (byte) (this.id * 10 + i);

            }
            buf.put(b);
            buf.flip();
            return buf;

        }

        @Override
        public void run() {
            Random r = new Random();
            while (r.nextInt(100) != 50) {
                try {
                    System.out.println("Thread  " + id + " is Writing");
                    this.channel.write(this.generateStaticBytes(), this.startPosition);
                    this.startPosition += 10;
                } catch (IOException e) {
                    e.printStackTrace();

                }
            }
            latch.countDown();
        }
    }
}

到目前为止我所看到的:

  • Windows 7(NTFS 分区):线性运行(也就是一个线程写入,当它结束时,另一个线程开始运行)

  • Linux Parrot 4.8.15(ext4 分区)(基于 Debian 的发行版),带有 Linux Kernel 4.8.0:线程在执行期间混合

再次作为documentation说:

File channels are safe for use by multiple concurrent threads. The close method may be invoked at any time, as specified by the Channel interface. Only one operation that involves the channel's position or can change its file's size may be in progress at any given time; attempts to initiate a second such operation while the first is still in progress will block until the first operation completes. Other operations, in particular those that take an explicit position, may proceed concurrently; whether they in fact do so is dependent upon the underlying implementation and is therefore unspecified.

所以我建议首先尝试一下,看看您要将代码部署到的操作系统(可能是文件系统类型)是否支持并行执行 FileChannel.write 打电话

编辑:正如所指出的,以上并不意味着线程可以同时写入文件,它实际上是相反的,因为 write 调用的行为根据WritableByteChannel的契约(Contract)它清楚地指定一次只有一个线程可以写入给定文件:

If one thread initiates a write operation upon a channel then any other thread that attempts to initiate another write operation will block until the first operation is complete

关于java - Java中RandomAccessFile的并发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45396252/

相关文章:

java - SwingWorker 没有停止

java - Oracle PL/SQL 中过程/函数和对象之间的区别

php - apache php > 用户请求

c++ - std::thread::join 是否保证写入可见性

java - 如何使用RandomAccessFile将UTF8数据写入xml文件?

java - 文件支持的 Java 映射

Java 泛型创建扩展类 A 并实现接口(interface) B 的对象列表

java - 双重检查锁定是否仅在惰性初始化场景中被破坏?

android-5.0-lollipop - 如何通过为 Lollipop 提供的 API 随机访问 SD 卡上的文件?

java - 访问堆栈顶部元素以递归比较两个堆栈元素是否相同的方法