異なる概念を混在させています。あなたは区別する必要があります。
- サーブレット3.0あたりとして非同期リクエストの受け渡しを、受信したサーブレットリクエストをWebコンテナのスレッドプールから切り離すことを可能にするAPI。その場でスレッドを作成するわけではありません。インターフェイスのユーザーは、適切なマルチスレッドソリューションを実装する必要があります。ノンブロッキングIOには関係しません。
- スレッドプール; Webコンテナ内のスレッドを取得および管理するためのメカニズムを提供します。 非同期要求ハンドブックには2つのオプションがあります。独自の
ExecutorService
を定義してリクエストを処理したり、Runnable
を新たに作成してAsyncContext
に送信したりすることができます(AsyncContext.start()
)。 Tomcatの場合、後者の方法では、server.xml
で定義されているTomcatのスレッドプールを使用します。
- ノンブロッキングIO(NIO); でも非同期ですが、それは別の話です。ディスクまたはネットワークIOのようなノンブロッキングIO操作に関連しています。 HTTPリクエスト処理にNIOを有効にする場合は、Tomcatのdocumentationを見てください。ザ・例以下
は、どのようにそれができる作業の概要を説明します。これは、ワーカー・ジョブに対して1つのスレッドのみを使用します。あなたは労働者がまだ実行され、一方、doGet
方法は、直ちに、終了していることがわかり
DATE THREAD_ID LEVEL MESSAGE
2011-09-03 11:51:22.198 +0200 26 I: >doGet: chrome
2011-09-03 11:51:22.204 +0200 26 I: <doGet: chrome
2011-09-03 11:51:22.204 +0200 28 I: >run: chrome
2011-09-03 11:51:27.908 +0200 29 I: >doGet: firefox
2011-09-03 11:51:27.908 +0200 29 I: <doGet: firefox
2011-09-03 11:51:32.227 +0200 28 I: <run: chrome
2011-09-03 11:51:32.228 +0200 28 I: >run: firefox
2011-09-03 11:51:42.244 +0200 28 I: <run: firefox
:あなたは、出力は次のようになり並列に2つの異なるブラウザからそれを実行する場合(私はカスタムロガーを使用します)。 2つのテストリクエスト:http://localhost:8080/pc/TestServlet?name=chrome
とhttp://localhost:8080/pc/TestServlet?name=firefox
。
簡単な例サーブレット
@WebServlet(asyncSupported = true, value = "/TestServlet", loadOnStartup = 1)
public class TestServlet extends HttpServlet {
private static final Logger LOG = Logger.getLogger(TestServlet.class.getName());
private static final long serialVersionUID = 1L;
private static final int NUM_WORKER_THREADS = 1;
private ExecutorService executor = null;
@Override
public void init() throws ServletException {
this.executor = Executors.newFixedThreadPool(NUM_WORKER_THREADS);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
final String name = request.getParameter("name");
LOG.info(">doGet: " + name);
AsyncContext ac = request.startAsync(); // obtain async context
ac.setTimeout(0); // test only, no timeout
/* Create a worker */
Runnable worker = new TestWorker(name, ac);
/* use your own executor service to execute a worker thread (TestWorker) */
this.executorService.execute(worker);
/* OR delegate to the container */
// ac.start(worker);
LOG.info("<doGet: " + name);
}
}
...とTestWorker
public class TestWorker implements Runnable {
private static final Logger LOG = Logger.getLogger(TestWorker.class.getName());
private final String name;
private final AsyncContext context;
private final Date queued;
public TestWorker(String name, AsyncContext context) {
this.name = name;
this.context = context;
this.queued = new Date(System.currentTimeMillis());
}
@Override
public void run() {
LOG.info(">run: " + name);
/* do some work for 10 sec */
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
ServletResponse response = this.context.getResponse();
response.setContentType("text/plain");
try {
PrintWriter out = response.getWriter();
out.println("Name:\t\t" + this.name);
out.println("Queued:\t\t" + this.queued);
out.println("End:\t\t" + new Date(System.currentTimeMillis()));
out.println("Thread:\t\t" + Thread.currentThread().getId());
out.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
this.context.complete();
LOG.info("<run: " + name);
}
}
あなたはこのを見てみたいことがあります。http://stackoverflow.com/questions/ 7749350/Tomcat 7で非同期処理を実装したい場合は、asynccontext-startasyncreq-resume-not-supported-on-asynccontextを使用してください。 – JVerstry