2011-06-02 42 views
0

首先,這可能是一個愚蠢的問題,但我希望有人會告訴我,以及爲什麼。我也很抱歉,如果我的解釋是什麼/爲什麼缺乏。使用帶Servlet的BlockingQueue來保存對象

我正在使用一個servlet來上傳一個巨大的(247MB)文件,這是描繪的管道(|)。我抓取20個字段中的5個,創建一個對象,然後將其添加到列表中。一旦完成,我將該列表傳遞給名爲persistList()的OpenJPA事務方法。

這將是可以的,除了文件的大小。這是永恆的,所以我正在尋找一種方法來改善它。我的想法是在新線程中將BlockingQueue與persist/persistList方法結合使用。不幸的是,我在java併發方面的技能有點弱。

我想做的事情有意義嗎?如果是這樣,有沒有人做過類似的事情?

+0

BlockingQueue的用途是什麼?是調用persistList()線程安全? – 2011-06-02 16:16:20

+0

就像我說的,我仍在研究這個想法。然而,一個想法是,一旦BlockingQueue達到說1000個元素,我調用drainTo()形成一個列表,然後啓動一個線程調用persistList()來堅持列表中的所有內容。 persistList()從工廠創建一個EntityManager,然後通過循環提交併調用flush()每n個元素。我不確定它是否線程安全。 – Jason 2011-06-02 16:23:52

回答

4

Servlets應該在很短的時間內響應請求。在這種情況下,文件內容的持久性需要是異步作業,因此:

  1. 該小服務程序應回覆一些關於上傳作業的文本,預計完成時間或類似內容。
  2. 上傳的內容應以二進制形式寫入某個臨時空間,而不是全部保存在內存中。這是多部分後期圖書館工作的常用方式。
  3. 您應該有一個單獨的服務阻止未決作業隊列。一旦找到工作,它就會處理它。
  4. 「作業」僅僅是上傳發生時寫入的臨時文件的一些句柄......以及任何元數據,比如誰上傳了它,作業ID等。
  5. 持續服務需要上傳大量的行,但是使其看起來像是「原子」,或者將中間狀態作爲表模型的一部分進行建模,或者寫入臨時空間。
  6. 如果您正在寫入臨時表,然後將所有內容複製到活動表中,請記住在數據庫級別具有足夠的日誌空間和臨時空間。
  7. 如果您有完整的J2EE堆棧,請考慮將作業隊列建模爲JMS隊列,以便恢復很有意義。再一次,請記住有適當的XA邊界,所以所有行持續存在於外部事務中。
  8. 最後,請考慮還有一個狀態檢查API和/或UI,您可以在其中確定任何特定上載作業的狀態:待處理/正在處理/已完成。
+0

好的,我想這不是一個好主意。不幸的是,由於它是一個巨大的上傳,servlet不會那麼快:首先BufferedReader處理文件,然後將列表發送到持久性服務。我的想法是,我可以通過向persistenceService發送塊來節省一些時間。不過,我不得不重讀你寫的很多東西來精神上處理它。 – Jason 2011-06-02 16:35:02

+0

喜歡大部分的答案,但不明白步驟5。不會使用數據庫事務是否足夠? – jtahlborn 2011-06-02 17:35:48

+0

這取決於正在寫入多少條記錄。在某些情況下,您無法在一次交易中寫入所有內容。提交的大小,鎖升級,併發性都會受到太大的影響。處理這種情況的一種方法是執行一組提交,每個提交的行數適中(顯然,每行提交很少有意義)。如果@Jason想這樣做,我暗示一種方法是向每一行添加一個字段,指示它是不完整上傳的一部分。 – 2011-06-02 18:14:29

相關問題