※synchronized
如果沒有同步,需要注意有可能用戶端同時傳的問題int i;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter out = resp.getWriter();
synchronized (this) {
this.i++;
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
out.println("a=" + i);
}
}
※先將synchronized註解,然後開啟兩個瀏覽器,因為設定停止2.5秒,所以假設瀏覽器1得到1,瀏覽器得到2,
然後按完瀏覽器1時,在2.5秒之內按下瀏覽器2,會發現3不見了,兩個都是4
※initial & Destroy
@Override
public void init() throws ServletException {
try (BufferedReader in = new BufferedReader(new FileReader("xxx"))) {
i = Integer.parseInt(in.readLine());
} catch (RuntimeException | IOException e) {
i = 0;
}
}
@Override
public void destroy() {
try (PrintWriter out = new PrintWriter(new FileWriter("xxx"))) {
out.println(i);
} catch (IOException e) {
e.printStackTrace();
}
}
int i;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter out = resp.getWriter();
// synchronized (this) {
this.i++;
// try {
// Thread.sleep(2500);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
out.println("a=" + i);
// }
}
※doGet和synchronized一樣,多init()和destroy(),xxx檔案前面沒有c:\之類的路徑,預設會放在eclipse.exe的地方
※第一次進來因為還沒有xxx檔案,所以會exception,就給它0
※server關閉時,就會存起來,起動時才去抓
※注意Eclipse有兩個按鈕很像,如下:
正常關閉是按Servers的紅鈕(Stop the server),但如果是按Console的紅鈕(Terminate)或者是按Eclipse右上角的╳,那就不會執行destroy(),所以如果突然斷電也是一樣
預設destroy是沒有執行任何東西,所以如果都不覆寫,按哪個就沒有關係
※三種變數
HelloServlet.java
public class HelloServlet extends HttpServlet {
static int classI = 0;
int i = 0;
static Map<HelloServlet, HelloServlet> mapInstances = new HashMap<>();
static List<HelloServlet> listInstances = new ArrayList<>();
static Set<HelloServlet> setInstances = new HashSet<>();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/plain; charset=UTF-8");
PrintWriter out = resp.getWriter();
i++;
out.println("實體變數=" + i);
mapInstances.put(this, this);
out.println("Map實體=" + mapInstances.size());
setInstances.add(this);
out.println("Set實體=" + setInstances.size());
listInstances.add(this);
out.println("List實體=" + listInstances.size());
classI++;
out.println("靜態變數=" + classI);
}
}
web.xml
<servlet> <servlet-name>ooo</servlet-name> <servlet-class>controller.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>ooo</servlet-name> <url-pattern>/xxx</url-pattern> </servlet-mapping> <servlet> <servlet-name>aaa</servlet-name> <servlet-class>controller.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>aaa</servlet-name> <url-pattern>/ooo</url-pattern> </servlet-mapping>
※結果參考:
實體變數=34 Map實體=1 Set實體=1 List實體=34 靜態變數=34
※只開一個瀏覽器或者開多個瀏覽器,但url最後都給xxx,結果就是34那三行一直變,Map實體和Set實體永遠都是1,因為Map的key和Set不可重覆
※另開一個瀏覽器,這次url最後給ooo,就會發現Map實體和Set實體是2了,而實體變數會從1開始,List實體和靜態變數是xxx和ooo的加總
※這個測試可以了解有幾個實體在run(Map實體和Set實體),每一個實體run了幾次(實體變數),全部的實體run了幾次(List實體、靜態變數)
※注意:我用3.0的@WebServlet(urlPatterns = { "/xxx", "/ooo" }),發現我給ooo和xxx,但Map實體和Set實體永遠都是1,可能設計的人認為既然一樣,就都給同一個實體吧!
又或者是版本問題,我用的是tomcat8(Servlet 3.1)

沒有留言:
張貼留言