![](/img/trans.png)
[英]Java BufferedReader.readLine() returning null when reading file
[英]BufferedReader readline when reading in a thread
我是Java並發編程的新手。
我需要閱讀,分析和處理一個快速增長的日志文件,因此我必須保持快速。 我的想法是(逐行)讀取文件,並且在匹配相關行之后,我希望將這些行傳遞給單獨的線程,這些線程可以對該行進行進一步處理。 在以下示例代碼中,我將這些線程稱為“ IOThread”。
我的問題是,IOthread.run()中的BufferedReader readline顯然永遠不會返回。 什么是讀取線程內Stream的有效方法? 有沒有比下面更好的方法了?
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
class IOThread extends Thread {
private InputStream is;
private int t;
public IOThread(InputStream is, int t) {
this.is = is;
this.t = t;
System.out.println("iothread<" + t + ">.init");
}
public void run() {
try {
System.out.println("iothread<" + t + ">.run");
String line;
BufferedReader streamReader = new BufferedReader(new InputStreamReader(is));
while ((line = streamReader.readLine()) != null) {
System.out.println("iothread<" + t + "> got line " + line);
}
System.out.println("iothread " + t + " end run");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class Stm {
public Stm(String filePath) {
System.out.println("start");
try {
BufferedReader reader = new BufferedReader(new FileReader(filePath));
PipedOutputStream po1 = new PipedOutputStream();
PipedOutputStream po2 = new PipedOutputStream();
PipedInputStream pi1 = new PipedInputStream(po1);
PipedInputStream pi2 = new PipedInputStream(po2);
IOThread it1 = new IOThread(pi1,1);
IOThread it2 = new IOThread(pi2,2);
it1.start();
it2.start();
// it1.join();
// it2.join();
String line;
while ((line = reader.readLine()) != null) {
System.out.println("got line " + line);
if (line.contains("aaa")) {
System.out.println("passing to thread 1: " + line);
po1.write(line.getBytes());
} else if (line.contains("bbb")) {
System.out.println("passing to thread 2: " + line);
po2.write(line.getBytes());
}
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Stm(args[0]);
}
}
輸入文件示例為:
line 1
line 2
line 3 aaa ...
line 4
line 5 bbb ...
line 6 aaa ...
line 7
line 8 bbb ...
line 9 bbb ...
line 10
使用輸入文件的文件名作為參數調用以上代碼。
出於以下原因,您的iothread中的閱讀器始終停留在while循環的第一次迭代的開頭:您從STM線程傳遞讀取行的內容,但不添加新的行字符(\\ n) 。 由於您的緩沖讀取器等待換行符(如.readLine()中的一樣),因此它將永遠等待。 您可以這樣修改代碼:
if (line.contains("aaa")) {
System.out.println("passing to thread 1: " + line);
byte[] payload = (line+"\n").getBytes();
po1.write(payload);
} else if (line.contains("bbb")) {
System.out.println("passing to thread 2: " + line);
byte[] payload = (line+"\n").getBytes();
po2.write(payload);
}
但是我不得不說這根本不是一個很好的解決方案,您可以使用阻塞隊列或類似的方法為IOThreads提供內容。 這樣,您可以避免將輸入轉換為字符串轉換為字節再轉換為字符串(而不是擺脫所有流)。
恕我直言,你已經倒退了。 創建多個線程以“處理”東西,而不是從文件中讀取數據。 從文件讀取數據時,總會遇到瓶頸,因此擁有多個線程不會有任何區別。 最簡單的解決方案是在給定線程中以最快的速度讀取行,並將行存儲在共享隊列中。 然后,任何數量的線程都可以訪問此隊列以進行相關處理。
這樣,您實際上可以在I / O或讀取器線程忙於讀取/等待數據的同時進行並發處理。 如果可能的話,將讀取器線程中的“邏輯”保持在最低限度。 只需閱讀這些行,然后讓工作線程執行真正繁重的工作(匹配模式,進一步處理等)。 隨線程安全隊列一起去,您應該是潔凈的。
編輯:使用BlockingQueue
某些變體,基於數組或基於鏈表。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.