有没有办法让java中的一个线程对某些FileInputStream或类似的进行读取调用,并且有第二个线程同时处理正在加载的字节? 我尝试了很多东西 - 我目前的尝试有一个线程运行:
FileChannel inStream;
try {
inStream = (new FileInputStream(inFile)).getChannel();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
int result;
try {
result = inStream.read(inBuffer);
} ...
第二个线程想要在加载时访问字节。显然,第一个线程中的读取调用将一直阻塞,直到缓冲区已满,但我希望能够在该点之前访问加载到缓冲区中的字节。目前,我尝试的所有内容都有缓冲区,并且它的后备数组保持不变,直到读取完成 - 这不仅打败了这个线程的点,而且还建议将数据加载到某个中间缓冲区,然后将其复制到我的缓冲区中,这似乎愚蠢。
一种选择是在后续读取中使用偏移对数组进行一堆较小的读取,但这会增加额外的开销。
有什么想法吗?
答案 0 :(得分:3)
当您按顺序读取数据时,操作系统会在您需要之前预读数据。由于系统已经为您完成此操作,您可能无法获得预期的好处。
为什么我不能让我的Filechannel或FileInputStream“流”进我的ByteBuffer或一些字节数组?
这就是它已经做的事情。
如果您想要更加无缝地加载数据,您可以使用内存映射文件,因为它“立即”出现在程序的内存中,并在您使用时在后台加载。
答案 1 :(得分:1)
我建议使用SynchronousQueue。 Reader将从队列中检索数据,编写器将“发布”文件中的数据。
答案 2 :(得分:1)
我通常对这样的要求做的是使用多个缓冲类实例,最好调整大小以允许有效加载 - 比如说多个簇大小。一旦第一个缓冲区被加载,将其排队,(即将其指针/实例推送到生产者 - 消费者队列),到将处理它的线程,并立即创建(或depool)另一个缓冲区实例,开始加载那个。要控制整体数据流,您可以在启动时创建适当数量的缓冲区对象,并将它们存储在“池队列”(另一个生产者 - 消费者队列)中,然后您可以将来自池中的数据的对象传播到文件读取线程,然后到缓冲区处理线程,而不是回到池。
这使得file->处理队列“充满”缓冲对象充满数据,不需要批量复制,没有不可避免的延迟,没有单个字节的低效线程间通信,没有缓冲锁定缓冲区索引,文件读取线程和数据处理线程无法在同一个缓冲区对象上运行。
如果您希望/需要使用threadPool来执行处理,您可以轻松地执行此操作,但如果您需要此子系统的任何结果输出与此子系统的顺序相同,则可能需要缓冲区对象中的序列号。它是从文件中读取的。
缓冲区对象还可能包含结果数据成员,异常/ errorMessage字段,以及您可能需要的任何内容。在重新执行之前,文件和/或结果数据可以容易地从数据处理转发到其他线程(例如,记录器或进度的GUI显示)。由于它只是指针/实例排队,因此大量数据将快速有效地流入您的系统。
答案 3 :(得分:0)
使用PipedInput / OutputStream创建一个带缓冲区的熟悉的管道。
如果需要,还可以使用FileInputStream来读取每个字节的字节数。 fis.read()函数不会阻塞,如果没有数据,它将返回-1,你可以随时检查available();