【发布时间】:2012-02-01 00:14:41
【问题描述】:
假设您有一个更大的文件,那么您有内存要处理。您想依次读取文件n 字节并且不会在此过程中被阻止
- 读取一个块
- 将其传递给线程
- 读取另一个块
- 将其传递给线程
我尝试了不同的方法并取得了不同程度的成功,但阻塞似乎总是问题所在。
请提供一个非阻塞方式的示例以获取访问权限,例如byte[]
【问题讨论】:
标签: java multithreading
假设您有一个更大的文件,那么您有内存要处理。您想依次读取文件n 字节并且不会在此过程中被阻止
我尝试了不同的方法并取得了不同程度的成功,但阻塞似乎总是问题所在。
请提供一个非阻塞方式的示例以获取访问权限,例如byte[]
【问题讨论】:
标签: java multithreading
你不能。
在等待磁盘为您提供数据时,您将总是阻塞。如果您对每个数据块有很多工作要做,那么使用第二个线程可能会有所帮助:该线程可以对数据执行 CPU 密集型工作,而第一个线程被阻塞等待下一次读取完成。
但这听起来不像你的情况。
最好的办法是尽可能大地读取数据(例如 1MB 或更多)。这可以最大限度地减少内核中阻塞的时间,并且可能会减少等待磁盘的时间(如果正在读取的块恰好是连续的)。
这里是密码
ExecutorService exec = Executors.newFixedThreadPool(1);
// use RandomAccessFile because it supports readFully()
RandomAccessFile in = new RandomAccessFile("myfile.dat", "r");
in.seek(0L);
while (in.getFilePointer() < in.length())
{
int readSize = (int)Math.min(1000000, in.length() - in.getFilePointer());
final byte[] data = new byte[readSize];
in.readFully(data);
exec.execute(new Runnable()
{
public void run()
{
// do something with data
}
});
}
【讨论】:
while(whatever) { byte[] chunk = new byte[1 << 10]; myInputStream.read(chunk); executorService.submit(theTaskUsing(chunk)); }
听起来您正在寻找流、缓冲或两者的某种组合(BufferedInputStream 有人吗?)。
检查一下: http://docs.oracle.com/javase/tutorial/essential/io/buffers.html
这是处理超大文件的标准方法。如果这不是您要找的东西,我深表歉意,但希望无论如何它都能帮助您流淌。
祝你好运!
【讨论】:
如果您有一个执行 I/O 和 CPU 计算的程序,如果平均而言,处理一个字节所需的 CPU 时间少于读取一个字节的时间,阻塞是不可避免的(在您的程序中的某处)。
如果您尝试读取需要磁盘寻道的文件,则数据可能在 10 毫秒内无法到达。一个 2 GHz CPU 在这段时间内可以完成 20 M 个时钟周期的工作。
【讨论】: