java - 如何使用多线程将多个txt文件读入一个列表?
问题描述
我正在学习Java中的多线程。为了练习,我想做多线程并行读取三个txt文件,将三个文件的每一行添加到一个List中。这是我的代码:
ArrayList<String> allLinesFromFiles= new ArrayList<String>();
Lock blockThread=new ReentrantLock();
Thread t = null;
for (String file : files) {
t= new Thread(new Runnable() {
@Override
public void run() {
try {
FileReader fichero;
fichero = new FileReader(file);
BufferedReader bufferFichero = new BufferedReader(fichero);
String line = bufferFichero.readLine();
while (line != null) {
writeList(line.toLowerCase());
line = bufferFichero.readLine();
}
bufferFichero.close();
}catch (IOException e) {
System.out.println("Error IO");
}
}
private void writeList(String line) {
blockThread.lock();
allLinesFromFiles.add(line);
blockThread.unlock();
}
});
t.start();
}
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
Collections.sort(allLinesFromFiles);
我在方法“writeList”中使用了锁定/解锁(ReentrantLock)来同步,因为我认为可能需要三个线程写入 ArrayList。是正确的?我必须使用 CopyOnWriteArrayList 而不是 ArrayList 吗?
我使用 join() 来等待三个线程的完成,但我的代码无法正常工作。
解决方案
基于您的代码的一种简单方法是添加一个AtomicInteger
计数以知道读取线程是否结束,并且主线程等待结束:
List<String> files = Arrays.asList("a.txt", "b.txt", "c.txt");
ArrayList<String> allLinesFromFiles= new ArrayList<String>();
Lock blockThread=new ReentrantLock();
AtomicInteger count = new AtomicInteger(0); // counter
Thread t = null;
for (String file : files) {
t= new Thread(new Runnable() {
@Override
public void run() {
try {
FileReader fichero;
fichero = new FileReader(getClass().getClassLoader().getResource(file).getFile());
BufferedReader bufferFichero = new BufferedReader(fichero);
String line = bufferFichero.readLine();
while (line != null) {
writeList(line.toLowerCase());
line = bufferFichero.readLine();
}
bufferFichero.close();
}catch (IOException e) {
e.printStackTrace();
System.out.println("Error IO");
}finally {
count.getAndIncrement(); // counter ++
}
}
private void writeList(String line) {
blockThread.lock();
allLinesFromFiles.add(line);
blockThread.unlock();
}
});
t.start();
}
while (count.intValue() < 3) {
TimeUnit.MILLISECONDS.sleep(500);
}
Collections.sort(allLinesFromFiles);
System.out.println(allLinesFromFiles);
但是,更好的方法是:
List<String> filePaths = Arrays.asList("a.txt", "b.txt", "c.txt");
List<String> result = new ArrayList<>();
filePaths.parallelStream().forEach(filePath -> {
try {
List<String> strings = Files.readAllLines(
Paths.get(ReadTest.class.getClassLoader().getResource(filePath).toURI()));
result.addAll(strings);
} catch (IOException | URISyntaxException e) {
e.printStackTrace();
}
});
Collections.sort(result);
System.out.println(result);
推荐阅读
- python - 3D 张量 (PyTorch) 的全连接层内存不足
- node.js - (node:18896) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated error
- python - Python Selenium 找不到表
- xpath - 如何使用类型选择获取元素Xpath,而katalon中的Spy对象找不到它
- clean-architecture - 清洁架构:网关到网关的通信必须通过用例进行吗?
- reactjs - ChartJS 上未显示注释 - React
- java - getId3v1Tag() 返回 null
- javascript - 如何在 React 中将整数值从父道具传递给子道具
- java - 如何使用手动轮询运行 kafka 消费者
- javascript - 将数组更新为 mockAPI