今日は、春に非同期プログラミングを実行する方法を学びます。 Webサーバーがリクエストrequestを処理するスレッドがスレッドプールから取得されるスレッドは、説明が難しくないことを知っています。これは、Web要求の数が非常に大きい場合、リクエストが入ったときに処理スレッドの作成方法を作成する方法です。さらに、Webサーバーによって作成された処理スレッドは、デフォルトで最初から最後まで同期して実行されます。つまり、スレッドAが要求Bを処理する責任がある場合、Bがreturnない場合、スレッドAを処理することは他の要求を処理することができないため、Webサーバーの同時処理機能が大幅に制限されます。
したがって、スレッドプールはスレッドリサイクルの問題を解決するので、同期処理要求を解決する方法は?答えは非同期処理です。非同期処理とは何ですか?非同期処理により、主に上記の要求が完了する前に上記のB要求をアイドル状態にすることができ、スレッドAを解放して他のリクエストを処理し続けることができます。次に、これを行い、スレッドA内でスレッドCを再起動してタスクを実行し、Webサーバーに直接戻ることを可能にし、新しいリクエストを受け入れ続けます。
以下の説明を開始する前に、最初に2つの概念をここで区別します。
1。プロセススレッド
処理スレッドはWebサーバーに属し、ユーザーリクエストの処理を担当し、スレッドプールで管理されています
2。非同期スレッド
非同期スレッドはユーザー定義のスレッドであり、スレッドプールで管理できます。
Springは、非同期タスクのサポートを提供します。非同期タスクは、 WebAsyncTaskクラスを使用して実装できます。同時に、タスクがタイムアウトしたときの処理方法や例外をスローする方法など、非同期タスクの対応するコールバック処理を設定することもできます。非同期タスクは通常非常に実用的です。たとえば、非同期スレッドに長時間処理される可能性のある操作を残して処理するか、注文が支払われたときに、非同期タスクが注文の支払い結果を照会することを可能にします。
1。通常の非同期タスク
デモンストレーションの利便性のために、非同期タスクの実行はThread.sleep(long)を使用してシミュレートされます。ここで、ユーザーが次のインターフェイスを要求すると仮定します。
http://localhost:7000/demo/getUserWithNoThing.json
非同期タスクインターフェイスは、次のように定義されています。
/***例外なしに非同期タスクをテスト*/@requestMapping(value = "getUserWithNothing.json"、method = requestmethod.get)public webasynctask <string> getUserwithNothing(){//印刷処理スレッド名System.Err.err.println( "メインスレッド名は" + swers.currentthread(); //これは、10Sのタイムアウトで非同期タスクを開くことをシミュレートします。webasynctask<string> task1 = new webasynctask <string>(10 * 1000l、() - > {system.err.println( "最初のスレッド名は" + thread.currentthread()。 「タスク1は正常に実行されます!例外はありません!」 //タスク実行が完了したときにメソッドが呼び出されます1.oncompletion(() - > {system.err.println( "タスク1が完了!");}); system.err.println( "task1は他のことを処理し続けます!"); task1を返す;}コンソールは次のように印刷します:
メインスレッド名はHTTP-NIO-7000-EXEC-1です
task1は他のことを扱い続けます!
最初のスレッド名はMVCASYNC1です
タスク1が完了しました!
ブラウザの結果は次のとおりです。
2。例外を超える非同期タスク
インターフェイスコール: http://localhost:7000/demo/getUserWithError.json
/***エラーが発生する非同期タスクをテスト* @return*/ @requestMapping(value = "getUserWitherror.json"、method = requestmethask.get)public webasynctask <string> getUserWitherror(){system.err.println( "メインスレッド名は" + currentthread.currentthread()非同期タスク。 webasynctask <string> task3 = new webasynctask <String>(10 * 1000l、() - > {System.err.println( "2番目のスレッド名は" + thread.currentthread()。 - > {system.err.println( "============================================================================= ========================================================================================= ========================================================================================= ============================================================================================================================================ "========================================================================= ============================================================================== ============================================================================== ============================================================================== ============================================================================== ============================================================================== ============================================================================== ==============================================================================コンソール出力は次のとおりです。
メインスレッド名はHTTP-NIO-7000-EXEC-1です
task3は他のことを扱い続けています!
2番目のスレッド名はMVCASYNC1です
2018-06-15 09:40:13.538エラー9168 --- [NIO-7000-EXEC-2] OACCC [。[。[。] servlet.service()for servlet [dispatcherservlet]スロー例外java.lang.arithmeticexception: / by zero
com.example.demo.controller.getuserinfocontroller.lambda $ 5(getuserinfocontroller.java:93)〜[classes/:na]
atorg.springframework.web.context.request.async.webasyncmanager.lambda $ startcallableprocessing $ 4(webasyncmanager.java:317)〜
at java.util.concurrent.executors $ runnableadapter.call(executors.java:511)〜[na:1.8.0_161]
Java.util.concurrent.futuretask.run(futuretask.java:266)〜[na:1.8.0_161]
at java.lang.thread.run(thread.java:748)[Na:1.8.0_161]2018-06-15 09:40:13.539エラー9168 --- [NIO-7000-EXEC-2] OACCC [。[。[。]:servlet.service()for servlet.service()ネストされた例外はjava.lang.arithmeticexception: / zero]です。
java.lang.arithmeticexception: / by zero
com.example.demo.controller.getuserinfocontroller.lambda $ 5(getuserinfocontroller.java:93)〜[classes/:na]
atorg.springframework.web.context.request.async.webasyncmanager.lambda $ startcallableprocessing $ 4(webasyncmanager.java:317)〜
at java.util.concurrent.executors $ runnableadapter.call(executors.java:511)〜[na:1.8.0_161]
Java.util.concurrent.futuretask.run(futuretask.java:266)〜[na:1.8.0_161]
at java.lang.thread.run(thread.java:748)[Na:1.8.0_161]==================================================================================
ミッション3が発生しました!
タスク3が完了しました!
もちろん、ユーザーの意見には友好的ではないように、上記の例外処理を行うこともできます。例外処理については、Spring Boot/Spring Unified Error Handlingスキームの使用に関する私の記事の別の記事をご覧ください
ブラウザ出力の結果:
3。タイムアウト非同期タスク
インターフェイスコール: http://localhost:7000/demo/getUserWithTimeOut.json
/***タスクがタイムアウトした非同期タスクをテスト* @return*/ @requestMapping(value = "getUserWithTimeout.json"、method = requestmethod.get)public webasynctask <string> getUserwithTimeout(){system.err.println( "メインスレッド名 +スレッド。 //これは非同期タスクを開始するためにシミュレートされます。10SWebAsynctask<String> task2 = new WebAsynctask <String>(10 * 1000L、() - > {System.err.println( "2番目のスレッド名は" + thread.currentthread()。 //タスクタイムアウトはこのメソッドを呼び出しますtask2.ontimeout(() - > {{ System.err.println( "================================================================================ ============================================================================================================================================ ============================================================================================================================================ ============================================================================================================================================ "========================================================================= ============================================================================== ============================================================================== ============================================================================== ============================================================================== ============================================================================== ============================================================================== ==============================================================================コンソール実行結果:
メインスレッド名はHTTP-NIO-7000-EXEC-4です
Task2は他のことを扱い続けています!
2番目のスレッド名はMVCASYNC2です
============================================================================================
タスク2が完了しました!
ブラウザの実行結果:
4。スレッドプール非同期タスク
上記の3つのケースの非同期タスクは、デフォルトではスレッドプールメカニズムによって管理されません。つまり、リクエストが入っている場合、処理スレッドがリリースされますが、システムは各要求のMvcAsyncタスクスレッドを作成します。つまり、これは機能しません、オーバーヘッドは特に高くなっています!したがって、管理にはスレッドプールを使用し、 WebAsyncTaskクラスコンストラクターのThreadPoolTaskExecutorオブジェクトインスタンスを直接渡すことができます。
まず、上記の最初のケースで同時リクエストを実行するときに何が起こるかを見てみましょう(ここではhttp://localhost:7000/demo/getUserWithNoThing.jsonへの同時呼び出しをシミュレートします):
コンソール出力は次のとおりです。
最初のスレッド名はMVCASYNC57です
最初のスレッド名はMVCASYNC58です
最初のスレッド名はMVCASYNC59です
最初のスレッド名はMVCASYNC60です
最初のスレッド名はMVCASYNC61です
最初のスレッド名はMVCASYNC62です
最初のスレッド名はMVCASYNC63です
最初のスレッド名はMVCASYNC64です
最初のスレッド名はMVCASYNC65です
最初のスレッド名はMVCASYNC66です
最初のスレッド名はMVCASYNC67です
最初のスレッド名はMVCASYNC68です
最初のスレッド名はMVCASYNC69です
最初のスレッド名はMVCASYNC70です
最初のスレッド名はMVCASYNC71です
最初のスレッド名はMVCASYNC72です
最初のスレッド名はMVCASYNC73です
最初のスレッド名はMVCASYNC74です
最初のスレッド名はMVCASYNC76です
最初のスレッド名はMVCASYNC75です
最初のスレッド名はMVCASYNC77です
最初のスレッド名はMVCASYNC78です
最初のスレッド名はMVCASYNC79です
最初のスレッド名はMVCASYNC80です
スレッドプールは追加されていないため、100のリクエストが100の非同期タスクスレッドを開きます。これは特に高価で、推奨されません。
以下は、スレッドプールの実装です。
インターフェイスの呼び出し: http://localhost:7000/demo/getUserWithExecutor.json
/***テストスレッドプール* @return*/ @requestMapping(value = "getUserWithExecutor.json"、method = requestmethod.get)public webasynctask <string> getUserWithexecutor(){system.err.println( "メインスレッド名は" + thread.currentthread()。getName()。 //これは非同期タスクを開始するためにシミュレートされ、ここでスレッドプールが渡されます。 webasynctask <string> task1 = new webasynctask <String>(10 * 1000L、executor、() - > {system.err.println( "最初のスレッド名は" + thread.currentthread()。getName()。 //タスク実行が完了したときにこのメソッドを呼び出すtask1.oncompletion(() - > {system.err.println( "タスク4が完了!");}); System.err.println( "Task4は他のことを処理し続けます!"); task1を返す;}スレッドプールは次のように定義されています。
@configurationPublic class myexecutor {@bean public static pooltaskexecutor getexecutor(){threadpooltaskexecutor taskexecutor = new shoodpooltaskexecutor(); taskexecutor.setcorepoolsize(30); taskexecutor.setmaxpoolsize(30); taskexecutor.setqueuecapacity(50); taskexecutor.setThreadNamePrefix( "huang"); //非同期タスクスレッド名はhuangプレフィックスreturn taskexecutorです。 }}上記の同時テストを使用して、次の結果を得ることができます。
この記事のサンプルコードアドレス:https://github.com/smallercoder/webasynctask
スレッドプールを使用すると、サーバーリソースを節約し、サーバー処理機能を最適化できます。頻繁に使用することを忘れないでください!読んでくれてありがとう!あなたがそれがあなたに役立つと思うなら、始めてください!
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。