java - 将大量排队数据写入文件时出现内存错误

标签 java io queue

我不知道如何具体处理这个问题(Java 新手)。基本上我有一个程序会生成大量超出我内存的数据(例如,它有 10 GB 数据,而我有 4 GB 内存)。我决定 fork 一个线程来获取数据并将其写入磁盘,尽管我知道磁盘写入永远无法跟上生成数据的进程,但我希望我的应用程序能够与我写入磁盘的速度绑定(bind)。但过了一会儿,我遇到了堆内存不足错误。

以下是我认为相关的部分: 所有要写入的数据都放在这个变量中:

private static Queue<short[]> result =  new LinkedList <short[]> ();

这是保存到文件的部分:

   static class SaveToFile extends Thread {


        public void run() {
                FileWriter bw = null;
                try {
                    bw = new FileWriter("output.csv");
                    Thread.sleep(500); //delay the start so the queue can have some data
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            System.out.println("size of results during execution is " + result.size());
            while(!result.isEmpty()) {
                short[] current = result.poll();
                try {
                    bw.write(Arrays.toString(current) + "," + "\n");
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            try {
                bw.flush();
                bw.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("file writing is done");
        }
    }

我不确定我做错了什么,我是否需要将结果队列阻塞到一定大小,以便我的进程停止写入?或者我在写入文件时做错了什么,我显示的是非缓冲版本,但我尝试了 bufferedWriter 得到了相同的结果?我观察到,当程序运行时,文件大小为 0,只有当它崩溃时,它似乎才会写入。即使没有 bufferedWriter,它是否会将其保存在内存中,这可能会导致内存问题吗?

我的想法是,当 SaveToFile 线程清除队列时,它会为其他进程继续写入提供更多空间(这些是我正在运行的唯一线程,主程序和 SaveToFile)。

最佳答案

do I need to block the result's queue at a certain size so my process stops writing to it?

是的,你知道。生产者生成数据的速度快于写出数据的速度是导致进程内存不足的最可能原因。

另一个问题是 LinkedList 不是同步的,因此在使用 LinkedList 在线程之间传递数据时需要使用锁定。

要限制容量,您可以使用ArrayBlockingQueueLinkedBlockingQueue。作为额外的好处,两者都是线程安全的,因此不需要外部同步。

最后,如果您的代码是 I/O 密集型的(正如看起来的那样),那么将其拆分为两个线程可能不会获得相对较小的好处。这一点值得牢记,因为您可能引入所有这些额外的复杂性,但几乎没有任何好处。

关于java - 将大量排队数据写入文件时出现内存错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10787739/

相关文章:

machine-learning - 当向预训练的 CNN 添加层时,您是添加到开头还是后面。它像队列还是堆栈?

java - 使用 jOOQ 3.6+、纯 SQL 和 javac 编译器进行缓慢编译

java - 枚举类型的Android单元测试

java - 使用 Java printwriter 编写 Scala 文件 - 为什么文件编写器在此代码中停止?

c# - 将二进制文件读入结构

python - 使用单线程时 Queue.full() 是否可靠?

javascript - 没有回调的 jQuery 队列命令

java - 天基建筑?

java - OrientDB安装Raspberry Pi问题

c - scanf ("%d", &i) 不会读取超过 10 位的数字