2011-04-22 52 views
0

我正在用Java多線程編寫一個應用程序,我想要暫停和恢復。
線程正在逐行讀取文件,同時發現模式的匹配行。它必須繼續在我暫停線程的地方。爲了讀取文件,我將BufferedReader與InputStreamReader和FileInputStream結合使用。Java:暫停線程並獲取文件中的位置

fip = new FileInputStream(new File(*file*)); 
fileBuffer = new BufferedReader(new InputStreamReader(fip)); 

我使用這個FileInputStream,因爲我需要filepointer作爲文件中的位置。
處理這些行時,它會將匹配行寫入MySQL數據庫。要在線程之間使用MySQL連接,我使用ConnectionPool來確保只有一個線程正在使用一個連接。

問題是當我暫停線程並恢復它們時,幾條匹配線就消失了。我也嘗試從offset中減去buffersize,但它仍然有同樣的問題。

什麼是一個體面的方式來解決這個問題,或者我做錯了什麼?

更多的細節:

循環

// Regex engine 
    RunAutomaton ra = new RunAutomaton(this.conf.getAuto(), true); 
    lw = new LogWriter(); 

     while((line=fileBuffer.readLine()) != null) { 
      if(line.length()>0) { 
       if(ra.run(line)) { 
         // Write to LogWriter 
         lw.write(line, this.file.getName()); 
         lw.execute(); 
        } 
       } 
      } 
      // Loop when paused. 
      while(pause) { } 
     } 

文件

// Get the position in the file 
public long getFilePosition() throws IOException { 
    long position = fip.getChannel().position() - bufferSize + fileBuffer.getNextChar(); 
    return position; 
} 

計算的地方將其放入數據庫

  // Get the connector 
      ConnectionPoolManager cpl = ConnectionPoolManager.getManager(); 
      Connector con = null; 
      while(con == null) 
       con = cpl.getConnectionFromPool(); 
      // Insert the query 
      con.executeUpdate(this.sql.toString()); 
      cpl.returnConnectionToPool(con); 

回答

1

我覺得問題的根源在於你不應該減去bufferSize。相反,你應該減去緩衝區中未讀字符的數量。我不認爲有辦法解決這個問題。

我能想到的最簡單的解決方案是創建一個FilterReader的自定義子類,用於跟蹤讀取的字符數。然後疊流如下:

FileReader 
< BufferedReader 
< custom filter reader 
< BufferedReader(sz == 1) 

最後BufferedReader在那裏,這樣就可以使用輸入行...但你需要的緩衝區的大小設置爲1,從而讓您的過濾字符數的位置匹配該應用程序已達成。

或者,您可以在自定義過濾器閱讀器中實現自己的readLine()方法。

+0

就像我在之前的文章中所說的。我減去bufferSize,然後添加在緩衝區中讀取的字符。這樣你只減去緩衝區中未讀字符的數量。沒有辦法在標準的BufferedReader中得到這個,但我擴展了標準的BufferedReader來獲得已經被獲得的字符數量。 – Yoni 2011-04-22 09:53:50

+0

@Yoni - 也許問題是字符數與字節數有關。我認爲你不應該深入到文件通道去嘗試找出位置。只需在堆棧中的更高級別計數字符。 – 2011-04-22 10:03:20

2

下面是一個例子Ø我相信你在找什麼。您沒有展示太多的實現,因此很難調試可能給您帶來的空白。請注意,FileInputStream的位置將是8192的倍數,因爲BufferedReader正在使用該大小的緩衝區。如果您想使用多個線程來讀取相同的文件,您可能會發現this answer有幫助。

public class ReaderThread extends Thread { 
    private final FileInputStream fip; 
    private final BufferedReader fileBuffer; 
    private volatile boolean paused; 

    public ReaderThread(File file) throws FileNotFoundException { 
     fip = new FileInputStream(file); 
     fileBuffer = new BufferedReader(new InputStreamReader(fip)); 
    } 

    public void setPaused(boolean paused) { 
     this.paused = paused; 
    } 

    public long getFilePos() throws IOException { 
     return fip.getChannel().position(); 
    } 

    public void run() { 
     try { 
      String line; 
      while ((line = fileBuffer.readLine()) != null) { 
       // process your line here 
       System.out.println(line); 

       while (paused) { 
        sleep(10); 
       } 
      } 
     } catch (IOException e) { 
      // handle I/O errors 
     } catch (InterruptedException e) { 
      // handle interrupt 
     } 
    } 
} 
+0

我認爲這將是8192的倍數,所以這就是爲什麼我做了一個BufferedReader的擴展版本,在那裏我可以讀取變量nextChar,所以我從文件指針中減去8192,並將nextChar的值添加到它。這個例子是我現在擁有的,它不適合我。 – Yoni 2011-04-22 09:00:59

0

經過幾天的搜索,我發現確實減去緩衝區大小並在緩衝區中添加位置並不是正確的方法。這個位置從來都不對,我總是錯過了一些線條。
當尋找一種新的工作方式來完成我的工作時,我沒有計算字符的數量,因爲它只是太多的字符來計算哪些會降低我的表現。但我發現了別的東西。軟件工程師Mark S.Kolich創建了a class JumpToLine,它使用Apache IO庫跳轉到指定的行。它也可以提供最後一行,所以這真的是我需要的。
對於那些感興趣的人,他的主頁上有一些例子。