国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - 詳解Servlet 3.0/3.1 中的異步處理

詳解Servlet 3.0/3.1 中的異步處理

2020-09-07 09:02無知者云 Java教程

這篇文章主要介紹了詳解Servlet 3.0/3.1 中的異步處理,實例分析了servlet 3.0異步處理的技巧,非常具有實用價值,需要的朋友可以參考下

Servlet 3.0之前,Servlet采用Thread-Per-Request的方式處理請求,即每一次Http請求都由某一個線程從頭到尾負(fù)責(zé)處理。如果一個請求需要進(jìn)行IO操作,比如訪問數(shù)據(jù)庫、調(diào)用第三方服務(wù)接口等,那么其所對應(yīng)的線程將同步地等待IO操作完成, 而IO操作是非常慢的,所以此時的線程并不能及時地釋放回線程池以供后續(xù)使用,在并發(fā)量越來越大的情況下,這將帶來嚴(yán)重的性能問題。即便是像Spring、Struts這樣的高層框架也脫離不了這樣的桎梏,因為他們都是建立在Servlet之上的。為了解決這樣的問題,Servlet 3.0引入了異步處理,然后在Servlet 3.1中又引入了非阻塞IO來進(jìn)一步增強(qiáng)異步處理的性能。

本文源代碼:https://github.com/davenkin/servlet-3-async-learning

項目下載地址:servlet-3-async-learning.rar

在Servlet 3.0中,我們可以從HttpServletRequest對象中獲得一個AsyncContext對象,該對象構(gòu)成了異步處理的上下文,Request和Response對象都可從中獲取。AsyncContext可以從當(dāng)前線程傳給另外的線程,并在新的線程中完成對請求的處理并返回結(jié)果給客戶端,初始線程便可以還回給容器線程池以處理更多的請求。如此,通過將請求從一個線程傳給另一個線程處理的過程便構(gòu)成了Servlet 3.0中的異步處理。

舉個例子,對于一個需要完成長時處理的Servlet來說,其實現(xiàn)通常為:

?
1
2
3
4
5
6
7
8
9
@WebServlet("/syncHello")
public class SyncHelloServlet extends HttpServlet {
 
  protected void doGet(HttpServletRequest request,
             HttpServletResponse response) throws ServletException, IOException {
    new LongRunningProcess().run();
    response.getWriter().write("Hello World!");
  }
}

為了模擬長時處理過程,我們創(chuàng)建了一個LongRunningProcess類,其run()方法將隨機(jī)地等待2秒之內(nèi)的一個時間:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class LongRunningProcess {
 
  public void run() {
    try {
 
      int millis = ThreadLocalRandom.current().nextInt(2000);
      String currentThread = Thread.currentThread().getName();
      System.out.println(currentThread + " sleep for " + millis + " milliseconds.");
      Thread.sleep(millis);
 
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

此時的SyncHelloServlet將順序地先執(zhí)行LongRunningProcess的run()方法,然后將將HelloWorld返回給客戶端,這是一個典型的同步過程。

在Servlet 3.0中,我們可以這么寫來達(dá)到異步處理:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@WebServlet(value = "/simpleAsync", asyncSupported = true)
public class SimpleAsyncHelloServlet extends HttpServlet {
 
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    AsyncContext asyncContext = request.startAsync();
 
    asyncContext.start(() -> {
      new LongRunningProcess().run();
      try {
        asyncContext.getResponse().getWriter().write("Hello World!");
      } catch (IOException e) {
        e.printStackTrace();
      }
      asyncContext.complete();
    });
 
  }

此時,我們先通過request.startAsync()獲取到該請求對應(yīng)的AsyncContext,然后調(diào)用AsyncContext的start()方法進(jìn)行異步處理,處理完畢后需要調(diào)用complete()方法告知Servlet容器。start()方法會向Servlet容器另外申請一個新的線程(可以是從Servlet容器中已有的主線程池獲取,也可以另外維護(hù)一個線程池,不同容器實現(xiàn)可能不一樣),然后在這個新的線程中繼續(xù)處理請求,而原先的線程將被回收到主線程池中。事實上,這種方式對性能的改進(jìn)不大,因為如果新的線程和初始線程共享同一個線程池的話,相當(dāng)于閑置下了一個線程,但同時又占用了另一個線程。

當(dāng)然,除了調(diào)用AsyncContext的start()方法,我們還可以通過手動創(chuàng)建線程的方式來實現(xiàn)異步處理:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@WebServlet(value = "/newThreadAsync", asyncSupported = true)
public class NewThreadAsyncHelloServlet extends HttpServlet {
 
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 
    AsyncContext asyncContext = request.startAsync();
 
    Runnable runnable = () -> {
      new LongRunningProcess().run();
      try {
        asyncContext.getResponse().getWriter().write("Hello World!");
      } catch (IOException e) {
        e.printStackTrace();
      }
      asyncContext.complete();
    };
 
    new Thread(runnable).start();
 
  }
 
}

自己手動創(chuàng)建新線程一般是不被鼓勵的,并且此時線程不能重用。因此,一種更好的辦法是我們自己維護(hù)一個線程池。這個線程池不同于Servlet容器的主線程池,如下圖:

詳解Servlet 3.0/3.1 中的異步處理

在上圖中,用戶發(fā)起的請求首先交由Servlet容器主線程池中的線程處理,在該線程中,我們獲取到AsyncContext,然后將其交給異步處理線程池??梢酝ㄟ^Java提供的Executor框架來創(chuàng)建線程池:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@WebServlet(value = "/threadPoolAsync", asyncSupported = true)
public class ThreadPoolAsyncHelloServlet extends HttpServlet {
 
  private static ThreadPoolExecutor executor = new ThreadPoolExecutor(100, 200, 50000L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(100));
 
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 
    AsyncContext asyncContext = request.startAsync();
 
    executor.execute(() -> {
 
      new LongRunningProcess().run();
 
      try {
        asyncContext.getResponse().getWriter().write("Hello World!");
      } catch (IOException e) {
        e.printStackTrace();
      }
 
      asyncContext.complete();
 
    });
  }
 
}

Servlet 3.0對請求的處理雖然是異步的,但是對InputStream和OutputStream的IO操作卻依然是阻塞的,對于數(shù)據(jù)量大的請求體或者返回體,阻塞IO也將導(dǎo)致不必要的等待。因此在Servlet 3.1中引入了非阻塞IO(參考下圖紅框內(nèi)容),通過在HttpServletRequest和HttpServletResponse中分別添加ReadListener和WriterListener方式,只有在IO數(shù)據(jù)滿足一定條件時(比如數(shù)據(jù)準(zhǔn)備好時),才進(jìn)行后續(xù)的操作。

詳解Servlet 3.0/3.1 中的異步處理

對應(yīng)的代碼示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
@WebServlet(value = "/nonBlockingThreadPoolAsync", asyncSupported = true)
public class NonBlockingAsyncHelloServlet extends HttpServlet {
 
  private static ThreadPoolExecutor executor = new ThreadPoolExecutor(100, 200, 50000L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(100));
 
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 
    AsyncContext asyncContext = request.startAsync();
 
    ServletInputStream inputStream = request.getInputStream();
 
    inputStream.setReadListener(new ReadListener() {
      @Override
      public void onDataAvailable() throws IOException {
 
      }
 
      @Override
      public void onAllDataRead() throws IOException {
        executor.execute(() -> {
          new LongRunningProcess().run();
 
          try {
            asyncContext.getResponse().getWriter().write("Hello World!");
          } catch (IOException e) {
            e.printStackTrace();
          }
 
          asyncContext.complete();
 
        });
      }
 
      @Override
      public void onError(Throwable t) {
        asyncContext.complete();
      }
    });
 
 
  }
 
}

在上例中,我們?yōu)镾ervletInputStream添加了一個ReadListener,并在ReadListener的onAllDataRead()方法中完成了長時處理過程。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

原文鏈接:http://www.jianshu.com/p/05a57d00d5cb

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 中文字幕在线精品 | 久久精品国产视频 | 完全免费av | 国产成人久久av免费高清密臂 | 久热久热 | 午夜影视 | 自拍偷拍亚洲欧美 | 国产精品女同一区二区久久夜 | 高清国产一区二区三区 | 最近日本韩国高清免费观看 | 日韩不卡一区二区 | 亚洲精品久久久久999中文字幕 | 欧美一级免费看 | 亚洲av毛片 | av男人的天堂在线 | 成人精品视频99在线观看免费 | 国产一区二区在线视频 | 日日做 | 亚洲一区二区视频在线观看 | 午夜黄色影院 | 亚洲一区二区三区四区五区中文 | 最近中文字幕免费mv视频7 | 久久久久久亚洲精品视频 | 羞羞的视频在线免费观看 | 簧片av| 成年人免费小视频 | 色综合久久久久 | 一区二区三区免费观看 | 欧美日韩成人 | 亚洲视频一区 | 欧美亚洲视频在线观看 | 免费特级黄毛片 | 国产精品一二三区视频 | 欧美一级二级三级视频 | 日韩一区二区观看 | 久久久国产精品视频 | 亚洲天堂第一页 | a免费视频| 国产成人精品免费 | 91视频网页版 | 黄色av免费在线 |