0

I am learning java thread and i wrote below code and try to run this code. i am not using any synchronize concept but output is in consistent format. Please help me to figure out the actual reason.

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();
        }
    }
}

I know that, write method of Writer class use synchronize block internally like :

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);
        }
    }

My program output is :

 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

My question is: why not second thread write data after first thread come out from synchronize block of write method. thanks :)

  • Without the `synchronized` keyword, it will not look like what you think. Your method is not synchronized at all, so they are working together but with the `sleep(500)` there is no way that one thread print more than one line before giving the hand to the other. – AxelH Mar 16 '17 at 14:08
  • @AxelH My question is, why data (output) is consistent without using synchronized??? Why not thread interference??? – sawai singh Mar 17 '17 at 04:33
  • Now that I understand the question, the "output" is from the file, so off course this seams synchronized using a BufferedWriter. See my edited answer to understand. – AxelH Mar 17 '17 at 06:42

1 Answers1

1

Well your question is badly written.

The output is correct, meaning that every thread are writting one line per half second, but what you didn't explain is that your "output" you are showing is in a file.

The BufferedWriter is only storing the text in a buffer, this is only during the close() that the writer will flush the buffer into the file.

Here is the code from BufferedWriter.close()

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

You see that it will flush the buffer there.

To prove it, you can flush the writer yourself during the loop :

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

This is why the constructor accept a int, this is the maximum size of the buffer, if you reach the size, it will flush automaticly.

Of course, you should know that this is easier to use one thread to write in a file, and your two threads that ask to the write thread to put the line in the file.

AxelH
  • 14,325
  • 2
  • 25
  • 55
  • @sawaisingh You are welcome, I rushed a bit yesterday because I had to go to a meeting ... but this morning I had more time to read the question again. – AxelH Mar 17 '17 at 09:51