为什么代码遵循同步?

Why code follow synchronization?

我正在学习 java 线程,我写了下面的代码并尝试 运行 这段代码。我没有使用任何同步概念,但输出格式一致。请帮我找出真正的原因。

package check;

import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;

public class Hello {
    public static void main(String[] args) throws FileNotFoundException, IOException {
        Write write = new Write();
        String str[] = new String[5];
        String str2[] = new String[5];

        for (int i = 0 ; i < 5; i ++) {
            str[i] = System.getProperty("line.separator") +  " hello this is a new line written at " + new Date().toString();
            str2[i] = System.getProperty("line.separator") +  " this is code after new line " + new Date().toString();
        }

        new Th(str, write).start();
        new Th(str2 , write).start();
    }
}

class Th extends Thread {
    private String[] message;
    private Write write;


    Th(String[] message, Write write) {
        this.message = message;
        this.write = write;
    }

    public void run() {
        try {
            write.write(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class Write {
    public void write(String[] message) throws IOException {
        FileWriter fileWriter = null;
        BufferedWriter bufferedWriter = null;
        try {
            fileWriter = new FileWriter("d:/a.txt", true);
            bufferedWriter = new BufferedWriter(fileWriter);
            for (String msg : message) {
                System.out.println(Thread.currentThread().getName());
                bufferedWriter.write(msg);
                Thread.sleep(500);
            }
        } catch (Exception e) {
            System.out.println(e);
        } finally {
            bufferedWriter.close();
            fileWriter.close();
        }
    }
}

我知道,Writer class 的写入方法在内部使用同步块,如:

public void write(String str, int off, int len) throws IOException {
        synchronized (lock) {
            char cbuf[];
            if (len <= WRITE_BUFFER_SIZE) {
                if (writeBuffer == null) {
                    writeBuffer = new char[WRITE_BUFFER_SIZE];
                }
                cbuf = writeBuffer;
            } else {    // Don't permanently allocate very large buffers.
                cbuf = new char[len];
            }
            str.getChars(off, (off + len), cbuf, 0);
            write(cbuf, 0, len);
        }
    }

我的程序输出是:

 this is code after new line Thu Mar 16 19:33:07 IST 2017
 this is code after new line Thu Mar 16 19:33:07 IST 2017
 this is code after new line Thu Mar 16 19:33:07 IST 2017
 this is code after new line Thu Mar 16 19:33:07 IST 2017
 this is code after new line Thu Mar 16 19:33:07 IST 2017
 hello this is a new line written at Thu Mar 16 19:33:07 IST 2017
 hello this is a new line written at Thu Mar 16 19:33:07 IST 2017
 hello this is a new line written at Thu Mar 16 19:33:07 IST 2017
 hello this is a new line written at Thu Mar 16 19:33:07 IST 2017
 hello this is a new line written at Thu Mar 16 19:33:07 IST 2017

我的问题是:为什么在第一个线程从写入方法的同步块出来后第二个线程不写入数据。 谢谢:)

嗯,你的问题写得不好。

输出是正确的,这意味着每个线程每半秒写一行,但是您没有解释的是您显示的 "output" 在一个文件中。

BufferedWriter 仅将文本存储在 缓冲区 中,这仅在 close() 期间写入器会将缓冲区刷新到文件中.

这是来自BufferedWriter.close()

的代码
public void close() throws IOException {
synchronized (lock) {
    if (out == null) {
    return;
    }
    try {
        flushBuffer();
    } finally {
        out.close();
        out = null;
        cb = null;
    }
}
}

你看到它会刷新那里的缓冲区。

为了证明这一点,你可以在循环中自己刷新 writer :

fileWriter.write(msg);
fileWriter.flush();

这就是构造函数接受一个int的原因,这是缓冲区的最大大小,如果达到该大小,它将自动刷新。

当然,你应该知道这样更容易使用一个线程写入文件,而你的两个线程要求写入线程将行放入文件。