2017-03-16 56 views
0

我正在学习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类使用同步块的方法在内部想:

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 

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

+0

没有'synchronized'关键字,它看起来不像你想象的那样。你的方法根本不同步,所以他们一起工作,但是用“睡眠(500)”,没有办法让一条线打印多条线,然后把手放到另一条线上。 – AxelH

+0

@AxelH我的问题是,为什么数据(输出)是一致的,而不使用同步?为什么不是螺纹干涉? –

+0

现在我明白了这个问题,“输出”来自文件,所以当然这个接口使用BufferedWriter进行同步。看到我编辑的答案了解。 – AxelH

回答

2

那么你的问题写得不好。

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

BufferedWriter只存储在缓冲器文本,这只是close(),作者将刷新缓冲器到文件中。

这里是BufferedWriter.close()

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

的代码你看,这将刷新缓冲区那里。

为了证明这一点,你可以在循环过程中刷新自己的作家:

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

这就是为什么在构造函数接受int,这是缓冲区的最大尺寸,如果达到大小,将自动刷新。

当然,您应该知道,使用一个线程写入文件更容易,并且您的两个线程要求写入线程将该行放入文件中。

+0

谢谢,现在对我们来说很清楚。非常感谢:) –

+0

@sawaisingh不客气,昨天我冲了一下,因为我不得不去开会......但今天早上我有更多时间再次阅读这个问题。 – AxelH