wait(),notify()-用于从文件中快速读取

时间:2018-09-26 21:11:16

标签: java filereader

我不明白为什么我从一行上的文件读取方法的速度这么慢。

下面是我班的一个例子。它的速度为10MB / 14秒。 同时,主要的延迟是由wait()和notify()引起的。为什么会这样?

import java.io.File;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class Reader {
    public static final String fileEnd = "=-=-=-=END=-=-=-=";


    private String nextLine;

    public Reader(File file){
        consume(file);
    }

    public String getLine(){
        String line;

        synchronized (this){
            while (true) {
                if(nextLine == null){
                    notify();


                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                else if(nextLine.equals(fileEnd)){
                    return fileEnd;
                }
                else {
                    line = nextLine;
                    nextLine = null;

                    notify();
                    break;
                }
            }
        }

        return line;
    }

    private void consume(File file){
        Thread thread = new Thread(()->{
            final char c = System.getProperty("line.separator").charAt(0);
            try (RandomAccessFile aFile = new RandomAccessFile(file, "r")){

                FileChannel inChannel = aFile.getChannel();
                ByteBuffer buffer = ByteBuffer.allocate(10240);

                StringBuilder line = new StringBuilder();
                while (inChannel.read(buffer) > 0) {
                    buffer.flip();


                    for (int i = 0; i < buffer.limit(); i++) {
                        char as = (char) buffer.get();

                        if(as==c){
                            String compliteLine = line.toString();
                            line = new StringBuilder();

                            compliteLine = compliteLine.replace("\r", "").replace("\n", "");


                            synchronized (this){
                                while (true) {
                                    if (nextLine == null) {
                                        nextLine = compliteLine;


                                        try {
                                            notify();
                                            wait();
                                        } catch (InterruptedException e) {
                                            e.printStackTrace();
                                        }
                                        break;
                                    } else {
                                        try {
                                            wait();
                                        } catch (InterruptedException e) {
                                            e.printStackTrace();
                                        }
                                    }
                                }
                            }

                        }
                        else {
                            line.append(as);
                        }

                    }

                    buffer.clear();
                }
                inChannel.close();

                synchronized (this){
                    notify();
                    wait();
                    nextLine = fileEnd;
                    notify();
                }
            }
            catch (Exception ignored){ignored.printStackTrace();}
        });

        thread.setPriority(Thread.MAX_PRIORITY);
        thread.setDaemon(true);
        thread.start();
    }
}

enter image description here

我也尝试在队列为100的ArrayBlockingQueue上执行相同的操作。 读取同一文件只需不到一秒钟的时间。 但是这个vseravno非常缓慢。 我自己上面的代码是为了加快阅读速度而提出的,但是它发生得更慢。

问题本身就是为什么代码比队列高,慢。 以及如何加速呢?

2 个答案:

答案 0 :(得分:1)

在上面的代码中,每行读取的Thread块。使用ArrayBlockingQueue,只有在线程从文件中读取100个项目之前,线程才将其阻塞。取决于处理将物品从队列中取出的速度有多快,它可能永远不会阻塞。

如果您想使上面的代码更快,您可以考虑使用多个缓冲区,以使Thread不需要阻塞每一行。本质上,您将自己实现BlockingQueue

答案 1 :(得分:0)

谢谢大家的帮助。 我被LinkedTransferQueue救出了。 完全可以按照我的需要工作。

import java.io.File;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.concurrent.LinkedTransferQueue;

public class LinkedTransferQueueReader {
    public static final String fileEnd = "=-=-=-=END=-=-=-=";


    private LinkedTransferQueue<String> queue = new LinkedTransferQueue<>();


    public LinkedTransferQueueReader(File file){
        consume(file);
    }


    public String getLine(){
        String line = "";


        try {
            line = queue.take();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


        return line;
    }

    private void consume(File file){
        Thread thread = new Thread(()->{
            final String lineSeparator = System.getProperty("line.separator");
            final char r = lineSeparator.charAt(0);
            char n = '\0';
            if(lineSeparator.length() > 1)
                n = lineSeparator.charAt(1);

            try (RandomAccessFile aFile = new RandomAccessFile(file, "r")){

                FileChannel inChannel = aFile.getChannel();
                ByteBuffer buffer = ByteBuffer.allocate(10240);

                StringBuilder line = new StringBuilder();
                while (inChannel.read(buffer) > 0) {
                    buffer.flip();


                    for (int i = 0; i < buffer.limit(); i++) {
                        char as = (char) buffer.get();

                        if(as == n)
                            continue;
                        if(as==r){
                            String compliteLine = line.toString();
                            line = new StringBuilder();


                            queue.transfer(compliteLine);

                        }
                        else {
                            line.append(as);
                        }

                    }

                    buffer.clear();
                }
                inChannel.close();

                queue.transfer(fileEnd);
            }
            catch (Exception ignored){ignored.printStackTrace();}
        });

        thread.setPriority(Thread.MAX_PRIORITY);
        thread.setDaemon(true);
        thread.start();
    }
}