java使用多线程读取大文件
时间: 2023-07-31 11:11:02 浏览: 117
在Java中,可以使用多线程来读取大文件,以提高读取效率。下面是一个简单的示例代码:
```java
import java.io.*;
import java.util.concurrent.*;
public class MultiThreadedFileReader {
private static final int THREAD_POOL_SIZE = 4; // 线程池大小
private static final int BUFFER_SIZE = 1024; // 缓冲区大小
public static void main(String[] args) throws Exception {
// 创建线程池
ExecutorService executor = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
// 打开文件
File file = new File("path/to/large/file");
FileInputStream fis = new FileInputStream(file);
// 计算每个线程需要读取的字节数
long fileSize = file.length();
long chunkSize = fileSize / THREAD_POOL_SIZE;
if (fileSize % THREAD_POOL_SIZE != 0) {
chunkSize++;
}
// 创建任务
CompletionService<byte[]> completionService = new ExecutorCompletionService<>(executor);
for (int i = 0; i < THREAD_POOL_SIZE; i++) {
long start = i * chunkSize;
long end = Math.min(start + chunkSize, fileSize);
completionService.submit(new FileReaderTask(fis, start, end));
}
// 等待任务完成并汇总结果
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (int i = 0; i < THREAD_POOL_SIZE; i++) {
Future<byte[]> future = completionService.take();
baos.write(future.get());
}
// 关闭流和线程池
fis.close();
executor.shutdown();
// 输出结果
System.out.println(new String(baos.toByteArray()));
}
static class FileReaderTask implements Callable<byte[]> {
private FileInputStream fis;
private long start;
private long end;
FileReaderTask(FileInputStream fis, long start, long end) {
this.fis = fis;
this.start = start;
this.end = end;
}
@Override
public byte[] call() throws Exception {
fis.getChannel().position(start);
byte[] buffer = new byte[BUFFER_SIZE];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
long bytesRead = 0;
while (bytesRead < end - start) {
int n = fis.read(buffer);
if (n == -1) {
break;
}
baos.write(buffer, 0, n);
bytesRead += n;
}
return baos.toByteArray();
}
}
}
```
上述代码中,使用了一个线程池来创建多个任务,每个任务负责读取文件的一部分数据。主线程等待所有任务完成后,将结果合并到一个字节数组中并输出。注意,在任务中需要使用`FileInputStream`的`getChannel()`方法获取文件通道,并在读取文件时使用`position()`方法设置偏移量,以确保每个线程读取的数据不重复。此外,还需要使用`ByteArrayOutputStream`来缓存每个线程读取的数据,并在任务完成后将它们合并到一个字节数组中。
阅读全文