我不熟悉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
使用输入文件的文件名作为参数调用上面的代码。
答案 0 :(得分:4)
您的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提供内容。这样你就可以避免将输入到字符串转换为字节并返回到字符串(而不是说要删除所有的流)。
答案 1 :(得分:2)
恕我直言,你已经倒退了。创建多个线程以“处理”内容而不是从文件中读取数据。从文件中读取数据时,无论如何都是瓶颈,因此拥有多个线程不会有任何区别。最简单的解决方案是在给定线程中尽可能快地读取行,并将行存储在共享队列中。然后,可以通过任意数量的线程访问此队列以执行相关处理。
这样,当I / O或读取器线程忙于读取/等待数据时,您实际上可以执行并发处理。如果可能,请在阅读器线程中将“逻辑”保持在最小值。只需阅读这些行,让工作线程完成真正繁重的工作(匹配模式,进一步处理等)。只需使用线程安全队列,你应该是犹太教。
编辑:使用BlockingQueue
的某些变体,基于数组或链接列表。