Java多线程操作文件异常:文件创建后无法写入且程序挂起
线程操作文件挂起且写入线程未执行的原因及修复
问题场景
用两个线程操作同一文件时,负责创建文件的Thread1执行完成,但写入内容的Thread2未执行写入操作,程序挂起无法正常退出。
程序输出
File created: example.txt Thread 1: File creation finished
完整代码
import java.io.*; public class ThreadWithFiles { private static final String FILE_PATH = "/Users/myUser/Desktop/example.txt"; public static void main(String[] args) { Object lock = new Object(); Thread thread1 = new Thread(() -> { synchronized (lock) { createFile(); System.out.println("Thread 1: File creation finished"); lock.notify(); } }); Thread thread2 = new Thread(() -> { synchronized (lock) { try { lock.wait(); populateFile(); lock.notify(); } catch (InterruptedException e) { e.printStackTrace(); } } }); // Start both threads thread1.start(); thread2.start(); try { synchronized (lock) { thread2.join(); lock.wait(); System.out.println("Main thread: Both actions terminated successfully"); } } catch (InterruptedException e) { e.printStackTrace(); } } private static void createFile() { try { File file = new File(FILE_PATH); if (file.createNewFile()) { String[] words = FILE_PATH.split("/"); String fileName = words[words.length - 1]; System.out.println("File created: " + fileName); } else { System.out.println("File already exists: " + FILE_PATH); } } catch (IOException e) { e.printStackTrace(); } } private static void populateFile() { try (FileWriter writer = new FileWriter(FILE_PATH, true)) { writer.write("Hello, this is some text to populate the file."); System.out.println("File populated with text"); } catch (IOException e) { e.printStackTrace(); } } }
原因分析
1. 主线程抢占锁导致Thread2无法执行
主线程在synchronized(lock)代码块内调用thread2.join(),此时主线程持有lock锁,而Thread2必须先获取lock锁才能执行wait()等待唤醒。Thread1执行完notify()释放锁后,主线程大概率先抢到锁,然后卡在thread2.join()等待Thread2结束,但Thread2因为拿不到锁根本无法启动执行,形成循环等待,程序挂起。
2. 主线程多余的wait()调用
主线程在thread2.join()后调用lock.wait(),此时没有其他线程会去唤醒主线程,导致主线程永久阻塞,程序无法退出。
修复方案
调整主线程的等待逻辑,移除不必要的同步锁和wait()调用,让Thread2能正常获取锁并执行:
import java.io.*; public class ThreadWithFiles { private static final String FILE_PATH = "/Users/myUser/Desktop/example.txt"; public static void main(String[] args) { Object lock = new Object(); Thread thread1 = new Thread(() -> { synchronized (lock) { createFile(); System.out.println("Thread 1: File creation finished"); lock.notify(); } }); Thread thread2 = new Thread(() -> { synchronized (lock) { try { lock.wait(); populateFile(); System.out.println("Thread 2: File population finished"); } catch (InterruptedException e) { e.printStackTrace(); } } }); // Start both threads thread1.start(); thread2.start(); try { // 直接等待两个线程执行结束,无需持有锁 thread1.join(); thread2.join(); System.out.println("Main thread: Both actions terminated successfully"); } catch (InterruptedException e) { e.printStackTrace(); } } private static void createFile() { try { File file = new File(FILE_PATH); if (file.createNewFile()) { String[] words = FILE_PATH.split("/"); String fileName = words[words.length - 1]; System.out.println("File created: " + fileName); } else { System.out.println("File already exists: " + FILE_PATH); } } catch (IOException e) { e.printStackTrace(); } } private static void populateFile() { try (FileWriter writer = new FileWriter(FILE_PATH, true)) { writer.write("Hello, this is some text to populate the file."); System.out.println("File populated with text"); } catch (IOException e) { e.printStackTrace(); } } }
修复要点
- 把
thread1.join()和thread2.join()移出synchronized(lock)代码块,避免主线程抢占Thread2需要的锁。 - 移除主线程中多余的
lock.wait()调用,线程执行完成后直接输出结果即可。 - Thread2执行完毕后无需调用
lock.notify(),因为没有其他线程等待该锁的通知。
内容的提问来源于stack exchange,提问作者user2418888
相关产品推荐
相关产品推荐

