2017-12-25 8 views
1

다른 응용 프로그램/프로세스에서 실제로 쓰고있는 파일에서 읽고 싶습니다.자바를 사용하여 적극적으로 쓰는 파일에서 읽음 [Improvement]

다른 질문에서 찾은이 코드는 작업을 수행합니다. 파일이 쓰여지는 동안 파일을 읽고 새 내용 만 읽습니다.

파일에 데이터가 추가되지 않아도 많은 CPU를 소비하는 문제. 이 코드를 어떻게 최적화 할 수 있습니까?

  • 타이머를 사용 하시겠습니까? 또는 thread.sleep을 일시 중지 하시겠습니까?

내가 추가하려는 또 다른 사항은 파일을 실시간으로 읽고 해당 내용을 처리하는 것입니다. 즉, thread.sleep 또는 타이머가 전체 프로그램을 일시 중지합니다. 내가 바라는 이상적인 개선은 몇 초를 기다리지 않고 특정 이벤트가 발생하는 것입니다.>새로운 데이터가 추가되었습니다. 이것이 가능한가 ?

public class FileReader { 
 

 
    public static void main(String args[]) throws Exception { 
 
     if(args.length>0){ 
 
      File file = new File(args[0]); 
 
      System.out.println(file.getAbsolutePath()); 
 
      if(file.exists() && file.canRead()){ 
 
       long fileLength = file.length(); 
 
       readFile(file,0L); 
 
       while(true){ 
 

 
        if(fileLength<file.length()){ 
 
         readFile(file,fileLength); 
 
         fileLength=file.length(); 
 
        } 
 
       } 
 
      } 
 
     }else{ 
 
      System.out.println("no file to read"); 
 
     } 
 
    } 
 

 
    public static void readFile(File file,Long fileLength) throws IOException { 
 
     String line = null; 
 

 
     BufferedReader in = new BufferedReader(new java.io.FileReader(file)); 
 
     in.skip(fileLength); 
 
     while((line = in.readLine()) != null) 
 
     { 
 
      System.out.println(line); 
 
     } 
 
     in.close(); 
 
    } 
 
}

답변

1

내가 찾고 있어요 이상적인 개선은 몇 초를 대기하는 것이 아니라, 특정 이벤트에 대한 는 => 새로운 데이터가 추가 발생할 수 있습니다. 이것이 가능한가 ?

베스트 솔루션 : 밀어 데이터 :

그 내용을 읽을 수 있기 때문에 함유량이 다른 애플리케이션을 알려야 생성 애플리케이션.

두 개의 서로 다른 응용 프로그램간에 정보를 전달할 수있는 채널을 사용할 수 있습니다.

예를 들어, 새로운 파일을 읽을 것을 알리기 위해 작성자가 업데이트하는 특정 파일을 사용합니다.
작성자는이 파일에 업데이트 날짜를 쓰거나 덮어 쓸 수 있으며이 날짜 이후에 내용을 읽지 않는 경우에만 데이터 파일을 읽습니다.

더 강력한 방법이지만 더 많은 오버 헤드가 있으면 리더 측에서 알림 서비스가 노출 될 수 있습니다.
왜 REST 서비스가 아닙니다.
이렇게하면 작성자는 새로운 콘텐츠가 준비되면 서비스를 통해 독자에게 알릴 수 있습니다.

추가하는 또 다른 것은, 내가 쓰기를 시도하고있는 전체 프로그램은 실시간으로 파일을 읽고 그 내용을 처리합니다. 즉, thread.sleep이거나 타이머가 전체 프로그램을 일시 중지합니다.

해결 방법 솔루션 : 당신은 아마 멀티 코어 CPU를

: 데이터는 특정 스레드에 의해 수행 당겨입니다.
생성 된 파일을 읽는 별도의 스레드를 만들어 응용 프로그램의 다른 스레드를 실행할 수있게하십시오.
게다가 정기적 인 일시 중지를 수행 할 수도 있습니다 : Thread.sleep() 읽기 스레드가 수행하는 코어 사용을 최적화합니다. MyReadingProcessingRunnable

Thread readingThread = new Thread(new MyReadingProcessing()); 
readingThread.start(); 

인 경우 :

그것은처럼 보일 수

public class MyReadingProcessing implements Runnable{ 

    public void run(){ 
      while (true){ 
       readFile(...); 
       try{ 
        Thread.sleep(1000); // 1 second here but choose the deemed reasonable time according the metrics of your producer application 
       } 
       catch(InterruptedException e){ 
        Thread.currentThread().interrupt(); 
       } 
       if (isAllReadFile()){ // condition to stop the reading process 
        return; 
       } 
      } 
    } 
} 
+0

답장을 보내 주셔서 감사합니다. 두 가지 응용 프로그램에 중점을 두려고하지 않습니다. 앞에서 언급했듯이 위의 코드는 알림을 보내는 작업을 수행합니다. 내가 해결하려고하는 문제는 스레드가 절대로 일시 중지되지 않으므로 응용 프로그램의 오버 헤드를 줄이는 것입니다. –

+0

당신은 오신 것을 환영합니다. 이해 했어. 나는 갱신했다. 유용 여부를 알려주도록하겠습니다. – davidxxx

+0

답변 해 주셔서 감사합니다. :). –

0

대신 바쁜 대기 루프의 변화 디렉토리 항목에 WatchService를 사용합니다.

Path path = Paths.get("..."); 
try (WatchService watchService = 
      path.getFileSystem().newWatchService()) { 
    WatchKey watchKey = path.register(watchService, 
      StandardWatchEventKinds.ENTRY_MODIFY); 
    for (;;) { // watchKey.poll with timeout, or take, blocking 
     WatchKey taken = watchService.take(); 
     for (WatchEvent<?> event : taken.pollEvents()) { 
      Path changedPath = (Path) event.context(); 
      if (changedPath.equals(path)) { 
       ... 
      } 
     } 
     boolean valid = taken.reset(); 
     if (!valid) { 
      ... unregistered 
     } 
    } 
} 

위의 사항은 폴링 또는 테이크를 사용하도록 조정되어야합니다.