Java8流和并发写入
我有这样的代码Java8流和并发写入,java,arraylist,stream,java-stream,Java,Arraylist,Stream,Java Stream,我有这样的代码 public static void main(String[] args) throws Exception { long start = System.currentTimeMillis(); List<String> matches = new Vector<>(); // Race condition for ArrayList?? BufferedReader reader = new Buffered
public static void main(String[] args) throws Exception {
long start = System.currentTimeMillis();
List<String> matches = new Vector<>(); // Race condition for ArrayList??
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("AHugeFile.txt")));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("output.txt")));
reader.lines().parallel()
.filter(s -> s.matches("someFancyRegEx"))
.forEach(s -> {
matches.add(s);
try {
writer.write(s);
writer.newLine();
} catch (Exception e) {
System.out.println("error");
}
}
);
out.println("Processing took " + (System.currentTimeMillis() - start) / 1000 + " seconds and matches " + matches.size());
reader.close();
writer.flush();
writer.close();
}
publicstaticvoidmain(字符串[]args)引发异常{
长启动=System.currentTimeMillis();
List matches=new Vector();//ArrayList的竞争条件??
BufferedReader=新的BufferedReader(新的InputStreamReader(新文件InputStream(“AHugeFile.txt”));
BufferedWriter writer=新的BufferedWriter(新的OutputStreamWriter(新的FileOutputStream(“output.txt”));
reader.lines().parallel()
.filter(s->s.matches(“someFancyRegEx”))
.forEach(s->{
匹配项。添加(s);
试一试{
作者:写;
writer.newLine();
}捕获(例外e){
System.out.println(“错误”);
}
}
);
out.println(“处理耗时”+(System.currentTimeMillis()-start)/1000+“秒和匹配数”+匹配数.size());
reader.close();
writer.flush();
writer.close();
}
我注意到,如果我在第3行用ArrayList替换向量,每次在匹配中都会得到不同的结果。我只是想把我的手弄脏在流上,但假设forEach同时执行,试图写入错过了一些写入的ArrayList!对于向量,结果是一致的
我有两个问题:
public void write(String s, int off, int len) throws IOException {
synchronized (lock) {
ensureOpen();
int b = off, t = off + len;
while (b < t) {
int d = min(nChars - nextChar, t - b);
s.getChars(b, b + d, cb, nextChar);
b += d;
nextChar += d;
if (nextChar >= nChars)
flushBuffer();
}
}
}
}
public void write(字符串s、int off、int len)引发IOException{
已同步(锁定){
重新打开();
int b=关,t=关+长;
而(b=nChars)
flushBuffer();
}
}
}
}
第一件事:定义是否关心行的写入顺序
第二:使用Java8提供的工具;它有两种非常方便的方法,分别是Files.lines()
和Files.write()
第三:正确处理你的资源!代码中不能保证文件描述符会正确关闭
第四:.matches()
将每次重新创建一个模式
,并且您总是使用相同的正则表达式进行筛选。。。你在浪费资源
第五:假设BufferedWriter
的写入方法是同步的,那么并行性不会带来太多好处
我会这样做:
public static void writeFiltered(final Path srcFile, final Path dstFile,
final String regex)
throws IOException
{
final Pattern pattern = Pattern.compile(regex);
final List<String> filteredLines;
try (
// UTF-8 by default
final Stream<String> srcLines = Files.lines(srcFile);
) {
filteredLines = srcLines.map(pattern::matcher)
.filter(Matcher::matches)
.collect(Collectors.toList());
}
// UTF-8 by default
Files.write(dstFile, filteredLines);
}
public static void writefilted(最终路径srcFile,最终路径dstFile,
最终字符串(正则表达式)
抛出IOException
{
最终模式=Pattern.compile(regex);
最终列表过滤线;
试一试(
//默认情况下为UTF-8
最终流srcLines=Files.lines(srcFile);
) {
filteredLines=srcLines.map(模式::匹配器)
.filter(Matcher::matches)
.collect(Collectors.toList());
}
//默认情况下为UTF-8
文件。写入(dstFile、filteredLines);
}
您应该使用Files.newBuffered{Reader,Writer}()
因为您使用的是Java 7+。更重要的是,Java8有文件.lines()
,您应该在试用资源时打开这些文件。-“但是您需要显式地处理同步,以使其在线程之间保持一致。”!很好的观点,特别是关于正则表达式,谢谢!我接受了先前的答案,因为它回答了我提出的两个问题,只是向你投了一票。注释,文件很大(大约60 GB),我想最好不要将匹配项存储在列表中,然后再编写它们。我想在阅读和匹配时写出。