Java 处理日志文件,在工作线程之间分配工作,以找到一个简单的总和
我想在线程之间分配工作。加载部分日志文件,然后将工作分发到处理部分文件 在我的简单示例中,我编写了800000行数据,每行都有一个数字。然后我对数字求和 当我运行这个例子时,我得到的总数稍微有点偏离。在这段线程代码中,您是否看到线程可能无法正确完成,因此无法计算总数Java 处理日志文件,在工作线程之间分配工作,以找到一个简单的总和,java,multithreading,Java,Multithreading,我想在线程之间分配工作。加载部分日志文件,然后将工作分发到处理部分文件 在我的简单示例中,我编写了800000行数据,每行都有一个数字。然后我对数字求和 当我运行这个例子时,我得到的总数稍微有点偏离。在这段线程代码中,您是否看到线程可能无法正确完成,因此无法计算总数 public void process() { final String d = FILE; FileInputStream stream = null; try {
public void process() {
final String d = FILE;
FileInputStream stream = null;
try {
stream = new FileInputStream(d);
final BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
String data = "";
do {
final Stack<List<String>> allWork = new Stack<List<String>>();
final Stack<ParserWorkerAtLineThread> threadPool = new Stack<ParserWorkerAtLineThread>();
do {
if (data != null) {
final List<String> currentWorkToDo = new ArrayList<String>();
do {
data = reader.readLine();
if (data != null) {
currentWorkToDo.add(data);
} // End of the if //
} while(data != null && (currentWorkToDo.size() < thresholdLinesToAdd));
// Hand out future work
allWork.push(currentWorkToDo);
} // End of the if //
} while(data != null && (allWork.size() < numberOfThreadsAllowedInPool));
// Process the lines from the work to do //
// Hand out the work
for (final List<String> theCurrentTaskWork : allWork) {
final ParserWorkerAtLineThread t = new ParserWorkerAtLineThread();
t.data = theCurrentTaskWork;
threadPool.push(t);
}
for (final Thread workerAboutToDoWork : threadPool) {
workerAboutToDoWork.start();
System.out.println(" -> Starting my work... My name is : " + workerAboutToDoWork.getName());
} // End of the for //
// Waiting on threads to finish //
System.out.println("Waiting for all work to complete ... ");
for (final Thread waiting : threadPool) {
waiting.join();
} // End of the for //
System.out.println("Done waiting ... ");
} while(data != null); // End of outer parse file loop //
} catch(Exception e) {
e.printStackTrace();
} finally {
if (stream != null) {
try {
stream.close();
} catch (final IOException e) {
e.printStackTrace();
}
} // End of the stream //
} // End of the try - catch finally //
}
公共作废流程(){
最终字符串d=文件;
FileInputStream=null;
试试{
流=新文件输入流(d);
最终BufferedReader读取器=新BufferedReader(新InputStreamReader(stream));
字符串数据=”;
做{
最终堆栈所有工作=新堆栈();
最终堆栈线程池=新堆栈();
做{
如果(数据!=null){
最终列表currentWorkToDo=新ArrayList();
做{
data=reader.readLine();
如果(数据!=null){
currentWorkToDo.add(数据);
}//if结束//
}while(data!=null&(currentWorkToDo.size()开始我的工作…我的名字是:”+workerAboutToDoWork.getName());
}//用于//
//正在等待线程完成//
System.out.println(“等待所有工作完成…”);
for(等待的最终线程:线程池){
正在等待。加入();
}//用于//
System.out.println(“完成等待…”);
}while(data!=null);//外部解析文件循环结束//
}捕获(例外e){
e、 printStackTrace();
}最后{
if(流!=null){
试一试{
stream.close();
}捕获(最终IOE例外){
e、 printStackTrace();
}
}//流的末尾//
}//try-catch finally的结束//
}
在进行此操作时,为什么不使用ThresholdLines大小的有界阻塞队列(ArrayBlockingQueue)进行添加。这将是您的生产者代码,您可以在其中读取行并使用放置在该队列上的方法进行阻塞,直到空间可用为止
正如Chris之前提到的,使用Executors.newFixedThreadPool()提交您的工作项。您的使用者将调用take()来阻止,直到元素可用为止
这不是地图/地图。如果您想要一个map/reduce,那么您需要在mix中的另一个队列中向其发布密钥。例如,如果要计算日志中的信息和调试事件数,则映射程序每次遇到提取的单词时都会将其排队。缩减器将使映射器的输出出列,并增加每个字的计数器。减缩器的结果将计算调试和信息的字数。在进行减缩时,为什么不使用ThresholdLines大小的有界阻塞队列(ArrayBlockingQueue)进行添加。这将是您的生产者代码,您可以在其中读取行并使用放置在该队列上的方法进行阻塞,直到空间可用为止 正如Chris之前提到的,使用Executors.newFixedThreadPool()提交您的工作项。您的使用者将调用take()来阻止,直到元素可用为止
这不是地图/地图。如果您想要一个map/reduce,那么您需要在mix中的另一个队列中向其发布密钥。例如,如果要计算日志中的信息和调试事件数,则映射程序每次遇到提取的单词时都会将其排队。缩减器将使映射器的输出出列,并增加每个字的计数器。减缩器的结果将计算调试和信息的字数。我确信,如果它是单线程的,它将更快、更简单。你先试过吗?您可能在如何添加线程类代码的总数(您没有显示)时遇到问题?您确定
thresholdLinesToAdd*numberofthreadsallowdinpool
大于您希望处理的行数吗?这可能是一个原因。我同意在一个线程中这很可能更快,但是如果你的目标是学习如何使用多个线程,我建议你看看Executors和AtomicInteger类。不,它在线程中运行得更快。我只是在试验线程。我很确定如果是单线程的话,它会更快更简单。你先试过吗?您可能在如何添加线程类代码的总数(您没有显示)时遇到问题?您确定thresholdLinesToAdd*numberofthreadsallowdinpool
大于您希望处理的行数吗?这可能是一个原因,我同意在一个线程中这很可能会更快,b