Java 使用生产者/消费者模型处理文件
在最近一篇被删除的帖子中,我问了以下问题:Java 使用生产者/消费者模型处理文件,java,multithreading,producer-consumer,Java,Multithreading,Producer Consumer,在最近一篇被删除的帖子中,我问了以下问题: 我正在尝试编写一个实现生产者/消费者模型的多线程程序。通常,我希望使用一个生产者从文件中读取行并将其放入BlockingQueue,然后让多个消费者在从BlockingQueue检索行并将结果存储在新文件中后进行一些处理 class Consumer implements Runnable { private String location; private BlockingQueue<String> blockingQu
我正在尝试编写一个实现生产者/消费者模型的多线程程序。通常,我希望使用一个生产者从文件中读取行并将其放入BlockingQueue,然后让多个消费者在从BlockingQueue检索行并将结果存储在新文件中后进行一些处理
class Consumer implements Runnable {
private String location;
private BlockingQueue<String> blockingQueue;
protected transient BufferedWriter bufferedWriter;
private String clusterName;
public Consumer (String location, BlockingQueue<String> blockingQueue) {
this.blockingQueue=blockingQueue;
this.location=location;
clusterName=location+".csv";
}
@Override
public void run() {
while (true) {
try {
//Retrieve the lines
String line = blockingQueue.take();
String result = doNormalize (line);
// TO DO
//
//bufferedWriter = new BufferedWriter(new FileWriter(clusterName, true));
//BufferedWriter.write(result+ "\n");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//Pattern pattern, Matcher matcher
private String doNormalize(String line){
String rules [] = getRules(); // return an array of Regex
String tmp="";
for (String rule : rules) {
Pattern pattern = Pattern.compile(rule);
Matcher matcher = pattern.matcher(line);
if (matcher.find()){
Set<String> namedGroups = getNamedGroupCandidates(rule);
Iterator<String> itr = namedGroups.iterator();
while(itr.hasNext()){
String value=itr.next();
tmp=tmp+matcher.group(value)+", ";
}
tmp = tmp + "\t";
break;
}
}
return tmp;
}
private Set<String> getNamedGroupCandidates(String regex) {
Set<String> namedGroups = new TreeSet<String>();
Matcher m = Pattern.compile("\\(\\?<([a-zA-Z][a-zA-Z0-9]*)>").matcher(regex);
while (m.find()) {
namedGroups.add(m.group(1));
}
return namedGroups;
}
}
我希望你能给我一些反馈意见,让我知道我应该如何取得高绩效。我花了几周时间阅读并发性和同步,因为我不想错过任何东西,但我正在寻找一些外部反馈。请在下面找到我需要的信息
- 为了获得更好的性能,我应该使用哪种类型的BlockingQueue实现?我不能使用固定大小的BlockingQueue,因为我们不知道文件中有多少行。或者我应该使用它,即使制作人将被锁定?(如果队列已满,则返回队列)
- 如果“f()”是生产者用来处理文件行的方法。知道我正在使用BlockingQueue,我是否应该同步f()?如果是,这不会影响我的申请吗?因为其他消费者将不得不等待锁的释放
你建议在提问之前实施一些东西,所以我删除了这篇文章并尝试实施这个模型。这是我的密码 我从文件中读取一个线程并将其放入阻止队列的生产者
class Producer implements Runnable {
private String location;
private BlockingQueue<String> blockingQueue;
private float numline=0;
protected transient BufferedReader bufferedReader;
protected transient BufferedWriter bufferedWriter;
public Producer (String location, BlockingQueue<String> blockingQueue) {
this.location=location;
this.blockingQueue=blockingQueue;
try {
bufferedReader = new BufferedReader(new FileReader(location));
// Create the file where the processed lines will be stored
createCluster();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
}
@Override
public void run() {
String line=null;
try {
while ((line = bufferedReader.readLine()) != null) {
// Count the read lines
numline++;
blockingQueue.put(line);
}
} catch (IOException e) {
System.out.println("Problem reading the log file!");
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void createCluster () {
try {
String clusterName=location+".csv";
bufferedWriter = new BufferedWriter(new FileWriter(clusterName, true));
bufferedWriter.write("\n");
} catch (IOException e) {
e.printStackTrace();
}
}
}
类生成器实现可运行{
私有字符串位置;
私有阻塞队列阻塞队列;
私有浮点numline=0;
受保护的瞬态缓冲读取器缓冲读取器;
受保护的瞬态缓冲写入程序缓冲写入程序;
公共生产者(字符串位置,阻塞队列阻塞队列){
这个位置=位置;
this.blockingQueue=blockingQueue;
试一试{
bufferedReader=新bufferedReader(新文件读取器(位置));
//创建用于存储已处理行的文件
createCluster();
}捕获(FileNotFoundException e1){
e1.printStackTrace();
}
}
@凌驾
公开募捐{
字符串行=null;
试一试{
而((line=bufferedReader.readLine())!=null){
//数一数读到的行数
numline++;
阻塞队列。放置(行);
}
}捕获(IOE异常){
System.out.println(“读取日志文件时出现问题!”);
e、 printStackTrace();
}捕捉(中断异常e){
e、 printStackTrace();
}
}
public void createCluster(){
试一试{
字符串clusterName=位置+“.csv”;
bufferedWriter=newbufferedwriter(newfilewriter(clusterName,true));
bufferedWriter.write(“\n”);
}捕获(IOE异常){
e、 printStackTrace();
}
}
}
消费者,其中多个线程将从BlockingQueue中删除,并执行一些处理“f()”并将结果存储在新文件中
class Consumer implements Runnable {
private String location;
private BlockingQueue<String> blockingQueue;
protected transient BufferedWriter bufferedWriter;
private String clusterName;
public Consumer (String location, BlockingQueue<String> blockingQueue) {
this.blockingQueue=blockingQueue;
this.location=location;
clusterName=location+".csv";
}
@Override
public void run() {
while (true) {
try {
//Retrieve the lines
String line = blockingQueue.take();
String result = doNormalize (line);
// TO DO
//
//bufferedWriter = new BufferedWriter(new FileWriter(clusterName, true));
//BufferedWriter.write(result+ "\n");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//Pattern pattern, Matcher matcher
private String doNormalize(String line){
String rules [] = getRules(); // return an array of Regex
String tmp="";
for (String rule : rules) {
Pattern pattern = Pattern.compile(rule);
Matcher matcher = pattern.matcher(line);
if (matcher.find()){
Set<String> namedGroups = getNamedGroupCandidates(rule);
Iterator<String> itr = namedGroups.iterator();
while(itr.hasNext()){
String value=itr.next();
tmp=tmp+matcher.group(value)+", ";
}
tmp = tmp + "\t";
break;
}
}
return tmp;
}
private Set<String> getNamedGroupCandidates(String regex) {
Set<String> namedGroups = new TreeSet<String>();
Matcher m = Pattern.compile("\\(\\?<([a-zA-Z][a-zA-Z0-9]*)>").matcher(regex);
while (m.find()) {
namedGroups.add(m.group(1));
}
return namedGroups;
}
}
类使用者实现可运行{
私有字符串位置;
私有阻塞队列阻塞队列;
受保护的瞬态缓冲写入程序缓冲写入程序;
私有字符串clusterName;
公共消费者(字符串位置,阻塞队列阻塞队列){
this.blockingQueue=blockingQueue;
这个位置=位置;
clusterName=位置+“.csv”;
}
@凌驾
公开募捐{
while(true){
试一试{
//取回线路
String line=blockingQueue.take();
字符串结果=doNormalize(行);
//做
//
//bufferedWriter=newbufferedwriter(newfilewriter(clusterName,true));
//BufferedWriter.write(结果+“\n”);
}捕捉(中断异常e){
e、 printStackTrace();
}
}
}
//模式模式匹配器匹配器
私有字符串不规范化(字符串行){
字符串规则[]=getRules();//返回正则表达式数组
字符串tmp=“”;
for(字符串规则:规则){
Pattern=Pattern.compile(规则);
匹配器匹配器=模式匹配器(线);
if(matcher.find()){
Set namedGroups=getNamedGroupCandidates(规则);
迭代器itr=namedGroups.Iterator();
while(itr.hasNext()){
字符串值=itr.next();
tmp=tmp+matcher.group(值)+“,”;
}
tmp=tmp+“\t”;
打破
}
}
返回tmp;
}
私有集GetNamedGroupPendidates(字符串正则表达式){
Set namedGroups=new TreeSet();
Matcher m=Pattern.compile(“\\(\\?”).Matcher(regex);
while(m.find()){
namedGroups.add(m.group(1));
}
返回namedGroups;
}
}
我的主类中的代码使用了1个生产者和3个消费者
BlockingQueue<String> queue = new ArrayBlockingQueue<>(100);
Producer readingThread = new Producer(location, queue);
new Thread(readingThread).start();
Consumer normalizers = new Consumer(location,queue);
ExecutorService executor = Executors.newFixedThreadPool(3);
for (int i = 1; i <= 3; i++) {
executor.submit(normalizers);
}
System.out.println("Stopped");
executor.shutdown();
BlockingQueue=newarrayblockingqueue(100);
Producer readingThread=新生产者(位置、队列);
新线程(readingThread.start();
消费者规范化器=新消费者(位置、队列);
ExecutorService executor=Executors.newFixedThreadPool(3);
对于(int i=1;i对于我的第二个问题:“单个消费者要“知道”多个消费者已经消费/处理了所有的行。”。我从这一点得到了灵感,结合了这个评论:每个消费者应该向队列2发送一条“i terminated”消息,如果单个输出消费者收到了所有这些,它也可以终止
因此,对于消费者而言,以下是我在run()
方法中编写的内容:
@Override
public void run() {
// A Consumer keeps taking elements from the queue 1, as long as the Producer is
// producing and as long as queue 1 is not empty.
while (true) {
try {
//Retrieve the lines
String line = firstBlockingQueue.take();
If a special terminating value is found.
if (line==POISON_PILL) {
// The consumer notifies other consumers and the SignleConsumer that operates on queue 2
// and then terminates.
firstBlockingQueue.put(POISON_PILL);
secondBlockingQueue.put(SINGLE_POISIN_PILL);
return;
}
// Put the normalized events on the new Queue
String result = doNormalize (line);
if (result!=null) {
secondBlockingQueue.put(result);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
if (line==SINGLE_POISIN_PILL) {
setCounter(getCounter()+1);
if (getCounter()== threadNumber) {
System.out.println("All "+getCounter()+" threads have finished. \n Stopping..");
try {
if (bufferedWriter != null)
{
bufferedWriter.flush();
bufferedWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
return;
}
}