2016-06-10 19 views
0

用Java編寫的我的RESTful服務消耗大量小文件(大約300字節),將它們寫入磁盤,將它們作爲BLOB插入到Oracle數據庫中,最後刪除它們。 爲防止由於網絡中斷導致丟失文件,或者如果磁盤上有多個文件,我必須將它們寫入磁盤進行批量插入。Java/Tomcat多線程(?)問題中的RESTful服務

我的問題是:如果我通過cURL和Windows批處理運行順序POST請求,一切都按預期無限期地工作,每秒大約3-5個文件。

如果我創建另一批來對服務器/服務進行基準測試,則會將某些文件雙倍插入到數據庫中。

它的工作原理是這樣的:POST request (octet-stream) -> RESTful service [ -> checks for valid file -> writes to disk -> directoryscanner reads all *.XYZ files in directory into String-array -> insert into DB -> if insert OK: delete file].

我相信由於我的服務的多線程性質,如果在一定時間內(比如:幾毫秒)兩個請求進行處理,兩個線程的插入過程插入相同的文件到數據庫中,一個線程刪除它們,第一個線程不能再找到該文件(因爲thread2已經刪除了它)等。

我的問題是:我怎麼能防止這種情況發生?我開始創建所有變量等私有,所以其他線程無法訪問它們(我相信這是它的工作原理)。但是,在兩個(或所有)線程共存的時間非常有限的情況下,thread2「竊取」來自thread1的文件,但之後,thread1已經插入了它。正如你大概可以推論的那樣,我不是專業的Java程序員,所以也許你可以指向正確的方向。讓我知道你是否需要代碼片段或任何東西。


EDIT
爲了闡明工作流程: 該服務通過HTTP POST獲取的數據的八位字節流至一些URI /service/{ID}/{file},其中ID是整數,並且文件是文件的請求中的擴展。
服務將文件寫入磁盤,然後將文件插入到數據庫(BLOB)中。
有時文件可能是一個zip壓縮文件,我必須提取, 然後將提取的文件插入到數據庫中。
在網絡中斷的情況下,我無法連接到數據庫。這就是爲什麼我將每個文件寫入磁盤,將它們讀入字符串數組並在連接重新啓動後立即將它們插入到數據庫中。

我想問題是,兩個線程同時寫入兩個文件,兩個線程都將文件掃描到自己的字符串數組中,兩個線程都會上傳文件。 (< - 這是我認爲我可能會錯的地方)。我可以重現這個問題,甚至3或4或5個批次,然後3或4或5個文件重複。

EDIT2(日誌示例)

10君-2016 09:56:14.400嚴重[池-275-線程1] ServiceResource.doSendData數組:file1.tst - [Ljava .lang.String; @ 3107ce05

10-Jun-2016 09:56:14.400 SEVERE [pool-274-thread-1] ServiceResource。doSendData數組:file1.tst - [Ljava.lang.String; @ 6996e2db

+1

聽起來像是你需要數據庫的約束,這樣數據庫,確保您不能插入重複(也許交易?)。但我不明白這些文件如何可以重複。它們是什麼以及2個請求如何引用同一個文件?你能解釋一下怎麼寫到磁盤上?什麼是目錄掃描器部分是需要的(你只是寫了(?)這些文件,爲什麼要掃描它們?) – zapl

+0

同步方法調用,那麼它將不能運行兩次,直到它已完成其工作 public synchronized void yourmethod(){ // do stuff } – David

+1

@zapl哦對不起,我忘了提及我不能在表中使用約束。我有時必須在數據庫中複製名稱來修復某些文件。至於「如何寫入磁盤......」,我會試着澄清一下我的問題。 – Lenniey

回答

0

好吧,我重新編碼了directoryscanner部分。現在我收到該文件,如果是zip文件,請提取它,獲取文件頭,將它們插入數據庫,最後在傳輸正確的情況下刪除它們。如果沒有連接到數據庫,則文件將被寫入磁盤,並且一旦數據庫再次聯機,就會將其插入到數據庫中。
感謝您的投入,我真的在這裏學到一些東西:)