2012-10-17 30 views
1

嘿,我想實現一個Java Servlet,它只爲每個用戶啓動一次線程。即使刷新它也不應該重新開始。我最後的做法給我帶來了一些麻煩,所以沒有代碼^^。任何關於servlet佈局的建議?爲每個訪問者啓動一個線程的Servlet

public class LoaderServlet extends HttpServlet { 
// The thread to load the needed information 
private LoaderThread loader; 
// The last.fm account 
private String lfmaccount; 

public LoaderServlet() { 
    super(); 
    lfmaccount = ""; 
} 

@Override 
protected void doPost(HttpServletRequest request, 
     HttpServletResponse response) throws ServletException, IOException { 
    if (loader != null) { 
     response.setContentType("text/plain"); 
     response.setHeader("Cache-Control", "no-cache"); 
     PrintWriter out = response.getWriter(); 
     out.write(loader.getStatus()); 
     out.flush(); 
     out.close(); 
    } else { 
     loader = new LoaderThread(lfmaccount); 
     loader.start(); 
     request.getRequestDispatcher("WEB-INF/pages/loader.jsp").forward(
       request, response); 
    } 
} 

@Override 
protected void doGet(HttpServletRequest request, 
     HttpServletResponse response) throws ServletException, IOException { 
    if (lfmaccount.isEmpty()) { 
     lfmaccount = request.getSession().getAttribute("lfmUser") 
       .toString(); 
    } 
    request.getRequestDispatcher("WEB-INF/pages/loader.jsp").forward(
      request, response); 
} 
} 

jsp使用ajax定期發佈到servlet並獲取狀態。線程只運行3分鐘,抓取一些last.fm數據。

+1

你可以發佈你試過的代碼麼? – Sathish

+0

你最後的做法是什麼?提供一些細節/代碼片段。只有這樣我們才能告訴你如何改進它。 –

+3

爲什麼你想爲每個用戶啓動一個線程?我認爲這種方法不可擴展,因爲它意味着如果你有1000個用戶,那麼你需要1000個線程(每個線程都有自己的堆棧,這可能會對你的內存造成嚴重破壞)。 – beny23

回答

0

假設它可以通過創建一個Map<String,Thread>來實現,然後你的servlet被調用它試圖用sessionId查找地圖。

只是一個草圖:

public class LoaderServlet extends HttpServlet { 

    private Map<String,Thread> threadMap = new HashMap<>(); 

    protected void doPost(..) { 
    String sessionId = request.getSesion().getId(); 
    Thread u = null; 
    if(threadMap.containsKey()) { 
     u = threadMap.get(sessionId); 
    } else { 
     u = new Thread(...); 
     threadMap.put(sessionId, u); 
    } 
    // use thread 'u' as you wish 
    } 

} 

注:

  • 這款採用會話ID的,而不是用戶線程
  • 看看ThreadPools,他們是偉大的
  • 作爲關聯意見提供者指出:同步問題不考慮在這個草圖
+2

在這個答案中有一個併發問題:如果在同一個會話中同時有兩個帖子會發生什麼? –

+0

我會盡力:)謝謝! – gausss

0

您的第一個任務是弄清楚如何唯一標識用戶,例如您如何辨別代理/ SOHO網關後面的不同用戶?

一旦你有了它,基本上只有一個單一對象爲用戶服務< - >線程映射到你的servlet。

然後我們進入可伸縮性問題,因爲@ beny23在上面的評論中提到了...我絕對贊同所提出的觀點 - 您的方法不是可靠的可伸縮性!

乾杯,

0

據我瞭解,你要避免來自同一用戶請求的並行處理。我建議你使用其他方法:將每個用戶的鎖關聯起來,並將其存儲在會話中。在開始處理用戶請求之前 - 嘗試獲取該鎖定。所以當前線程將等待來自該用戶的其他請求處理。 (使用會話監聽器存儲鎖定,創建會話時)

+0

這也是我第一次想到......也許值得一試...... – gausss

1

這裏您需要的是Session listener。每個瀏覽器會話只會調用一次方法sessionCreated()。所以,即使用戶刷新頁面,也不會有問題。 然後,您可以繼續併爲每個sessionCreated()方法調用啓動線程。

1

實現javax.servlet.SingleThreadModel =>服務方法不會同時執行。 請參閱servlet規範。

相關問題