Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用生产者/消费者模型处理文件_Java_Multithreading_Producer Consumer - Fatal编程技术网

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;
            }
        }