簡體   English   中英

在線程中讀取時,BufferedReader readline

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM