2014-07-03 47 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的理由很少。

相关问题