wait(), notify() - 用于快速读取文件
wait(), notify() - For fast reading from file
我不明白为什么我的读取一行文件的方法这么慢。
下面是我的例子class。它提供 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非常慢。
上面的代码是我自己想出来的,为了加快阅读速度,但它发生得更慢。
问题本身就是为什么代码比队列高,慢。
以及如何加速它?
在您上面的代码中,线程在读取的每一行上都会阻塞。使用 ArrayBlockingQueue
,如果线程在从队列中取出 100 个项目之前从文件中读取了 100 个项目,它只会阻塞。根据将项目从队列中取出的处理速度,它可能永远不会阻塞。
如果你想让上面的代码更快,你可以考虑拥有多个缓冲区,这样线程就不需要阻塞每一行。本质上,您将自己实施 BlockingQueue
。
谢谢大家的帮助。
我被 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 = '[=10=]';
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();
}
}
我不明白为什么我的读取一行文件的方法这么慢。
下面是我的例子class。它提供 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非常慢。 上面的代码是我自己想出来的,为了加快阅读速度,但它发生得更慢。
问题本身就是为什么代码比队列高,慢。 以及如何加速它?
在您上面的代码中,线程在读取的每一行上都会阻塞。使用 ArrayBlockingQueue
,如果线程在从队列中取出 100 个项目之前从文件中读取了 100 个项目,它只会阻塞。根据将项目从队列中取出的处理速度,它可能永远不会阻塞。
如果你想让上面的代码更快,你可以考虑拥有多个缓冲区,这样线程就不需要阻塞每一行。本质上,您将自己实施 BlockingQueue
。
谢谢大家的帮助。 我被 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 = '[=10=]';
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();
}
}