2016-08-24 81 views
0

我不確定以下情況的最佳解決方案是:在寫入數據庫時​​使用java讀取tcp流

我的Java程序永久從tcp-stream中讀取數據。同時,將這些數據保存到數據庫是必要的。應該寫入數據庫的數據量可能有所不同

我已經閱讀了很多關於消息隊列系統等等。詳細地說,我的解決方案會考慮使用LinkedBlockingQueue。從而,有兩個線程: 一個)啓動,其將執行從TCP流 b讀取)開始一個消費者威脅,這將從流中(解析)數據寫入到數據庫

生產者威脅在(示例 - )的代碼看起來像以下:

Main.java

public static void main(String[] args) { 
     LinkedBlockingQueue queue = new LinkedBlockingQueue(50); 
     Producer producer = new Producer(queue); 
     Consumer consumer = new Consumer(queue, producer); 

Produer.java

public class Producer implements Runnable { 
    private LinkedBlockingQueue queue; 
    private boolean running; 

    public Producer(LinkedBlockingQueue queue) { 
     this.queue = queue; 
     running = true; 
    } 

@Override 
    public void run() { 
    //read TCP-Stream here and save parsed messages to queue 
    } 
    public boolean isRunning() { 
     return running; 
    } 

Consumer.java

public class Consumer implements Runnable { 
    private Producer producer; 
    private LinkedBlockingQueue queue; 

    public Consumer(LinkedBlockingQueue queue, Producer producer) { 
     this.queue = queue; 
     this.producer = producer; 
    } 
    @Override 
    public void run() { 
     //insert data into database here 
     if(producer.isRunning()) { 
      //while producer is running, data needs to be inserted to database 
     } 
    } 

這是您會推薦使用的解決方案嗎?或者你知道更好的解決方案嗎?

謝謝!

+0

是的,這幾乎是一種標準方法。你也可以看看ExecutorService。複製[生產者/消費者線程使用隊列](http://stackoverflow.com/questions/2332537/producer-consumer-threads-using-a-queue)(因爲代碼不是特定於tcp /數據庫)。 –

+0

我沒有看到兩個線程的原因。我會一起做。沒有收穫。 – EJP

回答

2

你自己的建議非常好。

最終你試圖解決的是back pressure的問題,即如果你的數據接收速度比你寫的數據庫更快。這可能僅僅是因爲有大量數據到達或者僅僅是因爲你的目的地暫時不可用。無論哪種方式,這是你需要處理的情況。

在您提出的解決方案中,這由內存中的暫存區域(=您的隊列)處理。只要你有足夠的內存,並且你不會太在意停電的數據,那麼內存策略對你來說就可以正常工作。突發事件將被Java應用程序中越來越多的內存吸收。本身並不是一個問題,但請記住,當您的隊列最終耗盡時,JVM GC將啓動並從JVM堆中再次釋放內存。但從外部看,即從操作系統的角度來看,內存可能永遠不會被釋放。 JVM將內存釋放回操作系統是非常非常保守的。再次,在大多數情況下,這不是問題。

如果您有更嚴格的需求,那麼您需要考慮更「健壯」的臨時區域而不是RAM,例如本地磁盤。根據我的經驗,您提出的解決方案適合95%的用例。

+0

TCP將通過對發件人施加壓力自動處理背壓。應用程序無需參與此操作。 – EJP

+0

@EJP。我只是比你有更廣泛的「背壓」定義,而不僅僅是低層網絡的東西。 – peterh

+0

不,我們有相同的定義,我只是沒有看到應用程序涉及它的任何需要。如果你有兩個線程和一個隊列,你將不得不限制隊列,以免內存不足,所以你最終會得到TCP反壓,同時你沒有做任何有用的事情,你已經只是讀了很多你還沒有處理過的數據。重點是什麼? – EJP

相關問題