考虑以下代码示例,其中我删除了所有错误处理代码以使其可读:
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
的调用,程序会冻结。但是如果我将sleep方法的值设置得太高,执行也需要很长时间。
如何以更好的方式实现同样的目标?我已经看过Java多线程/并发编程资源,但没有任何东西(比如Java synchronized
)似乎适合这种情况。
答案 0 :(得分:1)
感谢您的评论,我再次查看了synchronized
/ 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杰出人物Josh Bloch严格建议不要在他的书 Effective Java 2nd Edition (来自this answer)中使用这些方法:
鉴于正确使用
wait
和notify
的困难,您应该使用更高级别的并发工具 [...]使用wait
和与notify
提供的高级语言相比,java.util.concurrent
直接类似于“并发汇编语言”编程。 很少(如果有的话)有理由在新代码中使用wait
和notify
。