2012-05-28 76 views
1

我不确定如何专门处理此问题(Java新增功能)。基本上我有一个程序产生大量超出我记忆的数据(例如,它的10个演唱会数据,我有4演出的RAM)。我决定分支一个线程来获取数据并将其写入磁盘,但我知道磁盘写入永远无法跟上生成它的进程,我希望我的应用程序能够快速写入磁盘。但过了一段时间,我发现堆内存错误。将大排队数据写入文件时发生内存错误

这里的部分,我认为是相关的: 的所有数据将被写入放在这个变量:

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)提供了更多空间。

回答

1

我是否需要将结果的队列以特定的大小阻塞,以便我的进程停止写入它?

是的,你这样做。生成器生成数据的速度比写出的速度快是导致进程内存不足的最可能原因。

另一个问题是LinkedList未同步,所以当使用LinkedList在线程之间传递数据时,您需要使用锁定。

要限制容量,可以使用ArrayBlockingQueueLinkedBlockingQueue。作为额外的好处,两者都是线程安全的,因此不需要外部同步。最后,如果你的代码是I/O绑定的,就像它看起来那样,你可能从分裂成两个线程中获得相对较少的好处。这值得铭记,因为它可能会导致所有这些额外的复杂性,而没有多少好处。

+0

我想如果内存已满,它会有相同的效果?它会停止写作,直到有更多的空间? –

+0

@ Error_404:不,它不这样做。 – NPE

+0

好的,谢谢,我将学习如何阻止和同步LinkedList.sorry是一种痛苦,但为什么我需要锁定?如果我正在写一个列表(result.add(data ...);)的结尾并从前端进行轮询,那么锁定的好处是什么? –

1

正如你已经说过的,你的盘写器比你的记录器慢。因此,我相信你永远不会到达同花顺部分,因为结果永远不会是空的。

我相信最好的方法是创建一个包含其中的队列的类并建立最大队列大小。所以,如果记录员试图排队的话会被阻塞。

我建议你的队列方法不会忙于等待,但还是要等待来自你的出队方法的信号。

相关问题