我有一个类似这样的FileReader类
public class FileReader extends Thread
{
private final Object lock = new Object();
public FileReader(String path, FileReaderCallback callback)
{
super(path);
this.path = path;
this.callback = callback;
}
@Override
public void run()
{
try
{
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(path)));
String info;
while ((info = reader.readLine()) != null)
{
synchronized (lock)
{
callback.onDone(path, info);
try
{
lock.wait();
}
catch (Exception ignored)
{
}
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void next()
{
synchronized (lock)
{
try
{
lock.notify();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
我有两个这个FileReader的实例,因为我想同时逐行读取两个文件。问题是我的代码只读取两个文件中的一行,然后它会暂停。
我在回调中调用该函数,如此
public void onDone(String path, String info)
{
reader1.next();
reader2.next();
}
那么问题是什么?!
提前致谢
答案 0 :(得分:1)
您同步lock
方法的next()
对象也会在while
方法的run
循环中使用。因此,无法从另一个线程中调用next()
方法的代码。
假设以下程序流程:
reader1
主题reader2
主题在某个时候,这两个线程中的一个开始。我们假设首先开始reader1
线程:
lock
对象next()
和reader1
上调用reader2
。此调用成功(但实际上是无操作)wait
对象上调用lock
。并等待...... 以后reader2
线程开始
lock
对象reader1.next()
时,它尝试从另一个线程同步到reader1
其lock
对象,从而使程序进入死锁状态。 / LI>
醇>
为了解决这个问题,我真的建议过度执行逐行同步的概念。一个简单的解决方法可能是为next()
方法使用不同的锁变量。
答案 1 :(得分:0)
在对同一个对象lock
持有锁定时,您正在调用侦听器回调。这将允许在调用wait之前调用notify。这将使你的线程永远等待。
你应该,
答案 2 :(得分:0)
您正面临着经典的死锁情景。让第一个锁为lock1
,第二个锁为lock2
。在您的第一个实例中,锁定状态可以表示如下:
synchronized (lock1) {
// start of onDone
synchronized (lock1) {
}
synchronized (lock2) {
}
// end of onDone
}
在第二个中,它是这样的:
synchronized (lock2) {
// start of onDone
synchronized (lock1) {
}
synchronized (lock2) {
}
// end of onDone
}
您应该像其他答案所暗示的那样优化您的逻辑。
您设计的另一个缺陷是;你也没有考虑可能的虚假唤醒。通常,您应该将wait()
来电置于while
循环中。