2017-03-16 55 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