MST

星途 面试题库

面试题:Java多线程环境下Java I/O的同步问题

在Java多线程环境中,当多个线程同时访问和操作Java I/O流(比如FileOutputStream)时,可能会出现数据混乱等问题。请描述如何使用`synchronized`关键字来确保I/O操作的线程安全,并给出一个简单示例。
12.4万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. 原理
    • synchronized关键字可以用于修饰方法或代码块。当一个线程进入被synchronized修饰的方法或代码块时,它会自动获取对象的锁。其他线程在该锁被释放前无法进入相同对象的同步代码块或方法,从而保证同一时间只有一个线程执行同步的代码,实现线程安全。
    • 对于FileOutputStream,可以通过对FileOutputStream对象或者包含FileOutputStream操作的类实例对象加锁来确保I/O操作的线程安全。
  2. 示例代码
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class ThreadSafeFileWriter {
    private final OutputStream outputStream;

    public ThreadSafeFileWriter(String filePath) throws IOException {
        this.outputStream = new FileOutputStream(filePath);
    }

    public void writeToFile(String content) {
        synchronized (this) {
            try {
                outputStream.write(content.getBytes());
                outputStream.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void close() {
        synchronized (this) {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

在上述代码中,ThreadSafeFileWriter类封装了FileOutputStream操作。writeToFileclose方法通过synchronized (this)同步代码块,确保同一时间只有一个线程可以执行这些I/O操作,从而保证线程安全。使用示例如下:

public class Main {
    public static void main(String[] args) {
        try {
            ThreadSafeFileWriter writer = new ThreadSafeFileWriter("test.txt");
            Thread thread1 = new Thread(() -> writer.writeToFile("Hello from thread 1"));
            Thread thread2 = new Thread(() -> writer.writeToFile("Hello from thread 2"));
            thread1.start();
            thread2.start();
            try {
                thread1.join();
                thread2.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这个Main类中,创建了两个线程同时调用writeToFile方法,由于writeToFile方法中的I/O操作是同步的,所以不会出现数据混乱的问题。