2017-03-16 2 views
0

자바 스레드를 배우고 코드 아래에 쓴 코드를 실행 해보십시오. 나는 어떤 동기 개념도 사용하고 있지 않지만 출력은 일관된 형식이다. 실제 이유를 알아 내도록 도와주세요.코드가 동기화를 따르는 이유는 무엇입니까?

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

나는, 작가 클래스 사용 동기화 블록의 방법을 쓰기 알고 내부적으로 좋아 :

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'키워드가 없으면 생각한 것처럼 보이지 않습니다. 당신의 메소드는 전혀 동기화되지 않았기 때문에 함께 작동하지만'sleep (500)'을 사용하면 한 스레드가 한 줄 이상을 출력하여 다른 한쪽으로 손을 넘기는 방법은 없습니다. – AxelH

+0

@AxelH 내 질문에, 왜 데이터 (출력) 동기화하지 않고 일관성이 ??? 왜 스레드 간섭하지 ??? –

+0

이제 질문을 이해했습니다. "출력"은 파일에서 발생하므로 물론이 이음새는 BufferedWriter를 사용하여 동기화됩니다. 이해할 수있는 편집 된 답변을 참조하십시오. – AxelH

답변

2

글쎄, 당신의 질문은 나쁘게 작성되었습니다.

출력이 정확합니다. 즉, 모든 스레드가 0.5 초마다 한 줄씩 기록되지만, 설명하지 않은 것은 출력중인 파일이 파일에 있음을 의미합니다.

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