2017-07-02 87 views
1

我想使用Servlets(resteasy + Hibernate)實現預約隊列。我的預約管理員 如下(當然簡化)。Java靜態同步vs BlockingQueue實現

public class AppoController{ 

public synchronized static int createAppoinment(AppObj app){ 
    //get last app no 
    //insert new app with no+1 
    //return new app no 
} 
} 

目前這種方法工作正常。但我已閱讀有關BlockingQueue實現這似乎是正確的方式?做工精細的

定義:
如果我不使用同步的靜態和一次多個約會發送多個請求具有相同的任命沒有
但是,如果使用同步靜態,約會與正確的順序創建

我沒有在這裏使用任何線程,但我認爲tomcat使用自己的線程來從用戶的服務器http請求。 所以這是一個多線程的應用程序?

我用Google搜索它過去幾天,但我得到的最接近的是Java/Android: Synchronized vs Queue implementation

什麼,我需要澄清的是,
- 這是做到這一點的正確方法嗎?
- 對我的場景使用同步靜態vs BlockingQueue實現有什麼優點和缺點。

任何你看起來相關的其他輸入也是受歡迎的。謝謝。

+0

我認爲這並不重要,因爲這兩種方法都侷限於單個JVM。如果您的服務受歡迎,那麼單個tomcat實例將無法處理所有流量。但是如果你將服務部署到第二個獨立的tomcat實例,兩種方法都不能保證唯一的預約號碼。因此解決這個問題的正確方法是讓數據庫生成預約號碼。 –

+0

+1提升縮放的影響。已經完全錯過了那部分!只是一個簡單的問題,是否有可能在同步靜態方法中耗盡服務器線程,因爲它們被阻塞(等待)?和阻塞隊列相反,線程(生產者)永遠不會被阻塞? – eric

+0

是的,但它是(a)已棄用,(b)計劃搬遷,和(c)絕對是你想要的最後一件事。只需同步您需要同步的內容,或者使用'java.util.concurrent.'中的某些內容' – EJP

回答

0

您的實施確實有效。同步方法只能由一個線程隨時執行。 Tomcat將使用多個線程(細節取決於當前設置,假設每個請求有一個線程),因此每個併發請求都會獲得自己的線程,然後請求等待此方法,直到其線程被允許進入方法。

我看到兩個選項,根據您的需要。

  1. 如果約會來自數據庫,讓數據庫或hibernate處理id生成。這會將多線程問題轉移到專爲處理這類問題而設計的數據庫中。
  2. 如果約會不是來自數據庫,並且您只需要約會對象的唯一標識符,請使用UUID(例如, java.lang.UUID.randomUUID()

實際上,如果您想要將約會的創建從HTTP請求中移出,實際上只使用Queue是有意義的。例如。如果在請求完成後像每夜批處理作業或專用工作線程池那樣創建預約。但是,如果創建約會是一項昂貴的操作,這隻會有意義。

在另一個主題上,你應該檢查這個方法是否需要是靜態的。

+0

是的約會可以使用oninsert觸發器從數據庫生成(我有幾個條件來確定新的應用程序否)。應用程序沒有創建是直接過程與百名用戶試圖訪問有限的應用程序沒有插槽集。 – eric

+0

'不會擴展'是誇大的多報。 *任何*解決方案都會涉及某種同步,信號量或鎖定。它的擴展程度完全取決於同步/信號量/鎖的* duration *。你自己的解決方案在這方面沒有什麼不同。 – EJP

+0

是啊,「不會規模」是過度誇張。我想指出的是,自己解決多線程問題通常是一個糟糕的主意。只需將問題移至專爲此類問題設計的系統,如數據庫即可。 –