2014-04-29 40 views
3

我已經寫了一個名爲AbcServlet.java Servlet中,在此我有一個Static String field called cacheSeller。它正在填充在小服務程序的方法initdoGet中。它是由一個CacheSellerClearThread.java清除如下圖所示:通過方法暴露Servlet的靜態字段 - 需要數據完整性

AbcServlet.java

public class AbcServlet extends HttpServlet { 

    private static String cacheSeller = null; 

    @Override 
    public void init() throws ServletException { 
     super.init(); 
     cacheSeller = populateCacheSeller(); 
    } 

    /** 
    * As soon as multiple requests are coming doGet is being called 
    */ 
    @Override 
    public void doGet(HttpServletRequest req, HttpServletResponse resp) 
      throws ServletException, IOException { 
     synchronized (this.getClass()) { 
      if (cacheSeller == null) { 
       cacheSeller = populateCacheSeller(); 
      } 
     } 

    } 

    private String populateCacheSeller() { 
     String fetchItFromSomewhere = "";// some logic to fetch the sting 
     return fetchItFromSomewhere; 
    } 

    public static synchronized void clearCacheSeller() { 
     cacheSeller = null; 
    } 
} 

CacheSellerClearThread.java

/** 
* This thread is clearing the string field cacheSeller of AbcServlet 
* 
*/ 
public class CacheSellerClearThread extends Thread { 

    public void run() { 
     while (true) { 
      try { 
       Thread.sleep(2000L); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      //Here it is clearing the static string field cacheSeller of AbcServlet 
      AbcServlet.clearCacheSeller(); 
     } 
    } 
} 

,如果你看一下代碼,正在讀cacheSeller值並在doGet方法中進行修改。所有請求線程將執行doGet,同時CacheSellerClearThread將在每2秒後清除其值。所以爲了保持cacheSeller值的數據完整性,我使用同步。

我需要的是有沒有其他的方式來實現這一目標,而不使用在clearCacheSeller方法顯式同步,並沒有在Servlet中應用明確的類級鎖的建議。 (我的意思是說使用任何先進的併發API,如原子參考或任何其他你可以建議。)

我已經寫了新的實現使用AtomicReference,請建議,我需要在任何地方使用同步。

public class AbcServlet extends HttpServlet { 

    private static AtomicReference<String> cacheSeller = new AtomicReference<String>(); 

    @Override 
    public void init() throws ServletException { 
     super.init(); 
     cacheSeller.set(populateCacheSeller()); 
    } 

    /** 
    * As soon as multiple requests are coming doGet is being called 
    */ 
    @Override 
    public void doGet(HttpServletRequest req, HttpServletResponse resp) 
      throws ServletException, IOException { 
     if (cacheSeller.get() == null) { 
      cacheSeller.compareAndSet(null, populateCacheSeller()); 
     } 
     resp.getWriter().print(cacheSeller.get()); 
    } 

    private String populateCacheSeller() { 
     String fetchItFromSomewhere = "";// some logic to fetch the sting 
     return fetchItFromSomewhere; 
    } 

    public static void clearCacheSeller() { 
     cacheSeller.set(null); 
    } 
} 
+1

第一,它從來就不是一個好主意,有@ niiraj874u我同意你的servlet類 – niiraj874u

+0

靜態實例變量,但這是我不能改變這是根據設計。 –

+0

你什麼時候創建並啓動線程來清除它?我認爲你知道init方法在其servlet的生命中只會被調用一次 – niiraj874u

回答

0

您可以使用類似Google Guava創建緩存。

例如:

LoadingCache<String, String> cache = 
CacheBuilder.newBuilder() 
.expireAfterWrite(2, TimeUnit.MINUTES) 
.build(loader); 

有這樣的事情,你可以避開你的輔助線程來清除緩存。

此實現是一個簡單的內存中緩存,它也是線程安全的。

問候

+0

是否有可能使用Java併發API類來使用別的不同步?我的意思是抽象鎖定功能的任何API。感謝使用Guava API的解決方案。 –

+1

我會建議AtomicReference – Dimitri

+0

@Dimitri你不覺得通過使用AtomicReference也需要明確的同步。請建議。 –

2

我會使用Executors框架建議。

Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(new Runnable() { 
      @Override 
      public void run() { 
       AbcServlet.clearCacheSeller(); 
      } 
     }, 2L,2L,TimeUnit.SECONDS); 

而在你doGet,僅同步初始化:

@Override 
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
      String localCacheSeller = cacheSeller; 
      if (cacheSeller == null) { 
       synchronized (this.getClass()) { 
        if (cacheSeller == null) { //need this because cacheSeller may already have been initialized while we waited 
         cacheSeller = populateCacheSeller(); 
         localCacheSeller = cacheSeller; //because the executor may clear it after we initialized 
        } 
       } 
      } 
    } 
+0

基本上你已經建議我使用Executor Framework來創建一個調度器。但我需要一些方法來避免顯式鎖定。順便說一句感謝您建議對空值進行雙重檢查。 –

相關問題