2012-05-28 28 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

正如你已經說過的,你的盤寫器比你的記錄器慢。因此,我相信你永遠不會到達同花順部分,因爲結果永遠不會是空的。

我相信最好的方法是創建一個包含其中的隊列的類並建立最大隊列大小。所以,如果記錄員試圖排隊的話會被阻塞。

我建議你的隊列方法不會忙於等待,但還是要等待來自你的出隊方法的信號。

相關問題