2014-07-03 49 views
1

考慮下面的代碼示例,其中我刪除了所有的錯誤,以保持它的可讀性處理代碼:如何延遲方法返回,直到文件完全讀

public class MyClass { 

    protected Something myAttribute; 
    protected boolean busy = true; 

    public ReactiveLogger() { 
    new Thread(new FileListener()).start(); 
    } 

    private class FileListener implements Runnable { 

    @Override 
    public void run() { 
     RandomAccessFile raf = new RandomAccessFile(LOG_FILE, "rw"); 
     while (true) { 
     final String line = cutFirstLine(raf); 
     if (line == null) { 
      busy = false; 
      Thread.sleep(1000); 
     } else { 
      busy = true; 
      // handeLogMessage changes myAttribute 
      handleLogMessage(line); 
     } 
     } 
    } 

    // definition of cutFirstLine etc. 

    } 

    // definition of handleLogMessage etc. 

    public Something getSomething() { 
    while (busy) { 
     Thread.sleep(100); 
    } 
    return myAttribute; 
    } 

} 

所以我MyClass類讀取的日誌文件背景(在另一個線程中),並使用從日誌文件中讀取的每一行更新屬性myAttribute。只要日誌文件中有條目並且我的屬性已更新,則應該延遲getter函數getMyAttribute()的返回值。只要日誌文件中沒有更多條目,getMyAttribute()應返回myAttribute

儘管此代碼示例按需要工作,但它似乎並不是最優雅的解決方案。目前尚不清楚線程應該睡多久以獲得最佳結果。如果只是在getter函數中刪除對Thread.sleep的調用,則程序將凍結。但是,如果我將睡眠方法的值設置得太高,則執行時間也會太長。

我怎樣才能以更好的方式實現相同?我已經看過Java多線程/併發編程資源,但沒有任何東西(如Java的​​)似乎適合這種情況。

+0

看看'Thread.join()' –

+0

根據你描述的目標,我不確定我明白爲什麼需要兩個線程。如果你的其他線程阻塞直到找到所需的結果,那麼不要打擾兩個線程。 –

+0

'Thread.join()'不能幫助afaik,因爲沒有線程可以結束。 'getSomething()'可以被多次調用。 'run()'方法永遠執行,因爲在任何時候,都可以將某些東西再次寫入日誌文件。 – Simon

回答

1

感謝評論,我再看看​​/wait()/notify()。所以這裏是另一個工作和更優雅的解決方案:

public class MyClass { 

    protected Something myAttribute; 
    protected boolean busy = true; 
    protected final Object lock = new Object(); 

    public ReactiveLogger() { 
    new Thread(new FileListener()).start(); 
    } 

    private class FileListener implements Runnable { 

    @Override 
    public void run() { 
     RandomAccessFile raf = new RandomAccessFile(LOG_FILE, "rw"); 
     while (true) { 
     final String line = cutFirstLine(raf); 
     if (line == null) { 
      busy = false; 
      synchronized (lock) { 
      lock.notifyAll(); 
      } 
      Thread.sleep(1000); 
     } else { 
      busy = true; 
      // handeLogMessage changes myAttribute 
      handleLogMessage(line); 
     } 
     } 
    } 

    // definition of cutFirstLine etc. 

    } 

    // definition of handleLogMessage etc. 

    public Something getSomething() { 
    synchronized (lock) { 
     while (busy) { 
     lock.wait(); 
     } 
    } 
    return myAttribute; 
    } 

} 

但是,仍然可能有更好的解決方案。 Java的傑出人物喬希布洛赫嚴格建議不要使用在他的書中這些方法有效的Java第二版(從this answer):

由於使用waitnotify正確的困難,你應該使用更高級別的併發工具與java.util.concurrent提供的高級語言相比,直接使用waitnotify類似於「併發彙編語言」編程。 很少,如果有的話,在新代碼中使用waitnotify的理由很少。

相關問題