2017-02-19 75 views
0

我有一個的FileReader類,這是這樣的Java的等待兩個線程通知作爲同一類

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

你的鎖在哪裏?你如何獲得它們?請包括你所有的課程。 – ram

+0

@ram我編輯了我的文章。我的鎖在FileReader類中,但onDone函數在其他地方(在我的主類中) – strings95

+0

'lock.wait()'你的運行代碼在該行,並且你永遠不會顯示你在哪裏調用next()' – nachokk

回答

1

lock對象在run方法您while循環中也使用。因此,您的next()方法的代碼不能從另一個線程中調用。

只是假設下面的程序流程:

  1. 你開始reader1螺紋
  2. 你開始reader2螺紋

在一段時間內這兩個線程的一個開始。假設reader1線程開始第一:

  1. 它同步到其lock對象
  2. 它從文件中讀取
  3. 它調用其回調線,即呼籲reader1reader2next()。此呼叫成功(但實際上是非操作)
  4. 它在其lock對象上調用wait。並等待...

在一段時間以後reader2線程開始

  1. 它同步到其lock對象
  2. 它從文件中讀取
  3. 它調用其回調線,但是,當調用reader1.next()時,它會嘗試同步來自另一個線程的reader1lock對象,從而使您的程序進入死鎖狀態。

爲了解決這個問題,我真的建議過度勞累如何執行逐行同步的概念。一個簡單的解決方法可能是爲您的next()方法使用不同的鎖定變量。

0

要調用監聽器回調,同時保持相同的對象lock上的鎖。這將允許在等待被調用之前調用通知。這會讓你的線程永遠等待。

你也應該

  1. 使用java.util.CountDownLatch這個問題。
  2. 使用ThreadPool。從線程擴展是老辦法,容易出錯。
  3. 您同步 next()方法
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循環中。