固定長スレッド池newFixedThreadPoolは要求に応答できません。キャッシュスレッド池newCachedThreadPoolスレッド数が増加してメモリがオーバーフローします。

93358 ワード

固定長スレッド池newFixedThreadPoolは要求に応答できません。キャッシュスレッド池newCachedThreadPoolスレッド数が増加してメモリがオーバーフローします。
  • 固定長さスレッド池newFixedThreadPool応答要求
  • キャッシュスレッド池newCachedThreadPoolスレッド数が継続的に増加し、メモリオーバーフローを引き起こす
  • 最後に、上記のHttpServerサービスのような要求処理を提供するスレッドプールの選択
  • について。
    固定長スレッド池newFixedThreadPoolは要求に応じられません。
    問題のシーン:開発服にhttpインターフェースが追加されました。テストチームの人員はこのインターフェースの一定回数をテストした後、安定的にhttpサービスのプロセスがキャンセルされませんでしたが、httpインターフェースはもう応答しません。
    Http Serverコードは以下の通りです。
    public class HttpServer extends Server {
    
    	public HttpServer(int port) {
    		super(port);
    	}
    
    	protected com.sun.net.httpserver.HttpServer server;
    	
    	//       
    	protected ExecutorService executor = Executors.newFixedThreadPool(2*Runtime.getRuntime().availableProcessors()+1);
    
    	public void bootstrap() {
    		try {
    			server = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(port), 0);
    			server.setExecutor(executor);
    			server.createContext("/", new HttpHandler());
    			server.start();
    
    			System.out.println("HttpServer bind: " + port);
    		} catch (Throwable e) {
    			e.printStackTrace();
    		}
    	}
    
    	public void shutdown() {
    		executor.shutdown();
    		server.stop(0);
    
    		System.out.println("HttpServer unbind: " + port);
    	}
    
    }
    
    注:Exectors.newFixedThreadPool(2*Runtime.getRuntime).available Processors()+1)ここで設定したスレッドのサイズは記事参照です。http://ifeve.com/how-to-calculate-threadpool-size/ ここのスレッドプールの長さは2 x 4+1です。
  • は、上記のシーン問題の原因を分析する前に、固定スレッド池newFixedThreadPoolとキャッシュスレッド池newCachedThreadPoolとを把握する。
  • newFixedThreadPoolは、スレッドの最大の同時数を制御し、オーバーしたスレッドはキューの中で待機します。
  • newCachedThreadPoolは、バッファ可能なスレッドプールを作成し、スレッドの長さが処理に必要以上であれば、空きスレッドを柔軟に回収し、回収可能でなければ新しいスレッドを作成します。
  • は上記の問題の原因を見に来ました。問題シーンでは、テスト担当者が新しいインターフェースを一定回数テストした後、http要求が発生しても応答がないということです。この問題を知った後、私の第一反応はプロセスに引っかかっていませんか?クラウドサーバーに登録して確認してみたら、httpサービスは正常に運行されています。異常な終了はありません。その後、アリ雲(サーバが選択したのはアリ雲サーバ)のバックグラウンド監視観察システムとプロセスのcpu、メモリ、ネットワークが正常に表示されます。そしてhttpサービスプログラムのログファイルを分析して、要求だけが応答していないことが分かりました。http要求は全部そうです。各http要求はスレッド池からスレッドを持って処理します。この時スレッド池に問題があると疑われます。直ちにjstackでhttpサービスの過程におけるスレッド情報を調べてみます。9つの同じインターフェースのスレッドがあり、しかもその新しいインターフェース処理スレッドがあります。スレッド情報を通じてコード内の指定された位置に問題があります。このインターフェースはタイムアウト操作があり、タイムアウト終了処理がされていません。時間がかかります。この異常インターフェースを訪問するたびに、スレッド池から受け取ったスレッドがずっと解放されないのをブロックします。jstackプリントのスレッド情報の中には、このエラーを処理するスレッドが9つあります。もう一度エラーインターフェースにアクセスしてスレッド情報を調べても、9つのブロックがあります。HttpServerのソースコードを調べてみたら、やはり固定長のスレッド池を使っています。
    //       
    	protected ExecutorService executor = Executors.newFixedThreadPool(2*Runtime.getRuntime().availableProcessors()+1);
    
  • jstack pidプリントプロセスでスレッド情報を分析しています。ここでは単にjstackコマンドを使っています。もっと詳しい機能はネットで探すとあります。もちろん時間があります。jstackの常用命令を紹介したいと思います。jstackが当時の情報を保存していなかったら、今は時間があります。当時の問題をシミュレーションして、わざとブロックされるインターフェース/wait/testを追加しました。このインターフェースのキーコードは一つです。デッドサイクル、つまりこのインターフェースの要求はブロックされます。
        @Override
        public void execute() {  //    /wait/test     
            try {
                while(true){
                    Thread.sleep(2000);//      HttpCmdWaitTest     14 ,        ,       
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            //
        }
    
    このインターフェースが9回を超えることを要求した後、jstack pidプリントスレッド情報(javaプログラム番号pidの検索は、jps-m-lまたはps-aux_;grep javaで見つかったjavaプログラムのプロセスIDを使ってもいいです。jdk開発デバッグツールをインストールしていないと、jps、aux javaプログラムは使えません。jstackならもう一つのブログを見てもいいです。どうやってインストールすればいいですか?https://blog.csdn.net/a704397849/article/details/88541377 )
  • jstack pidの印刷結果は、以下の通りである(スレッド情報が多い場合、ファイルにコンテンツをリダイレクトすることができる):
  • Full thread dump OpenJDK 64-Bit Server VM (25.201-b09 mixed mode):
    
    "Attach Listener" #23 daemon prio=9 os_prio=0 tid=0x00007fd1ec003800 nid=0x517f waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "pool-2-thread-9" #22 prio=5 os_prio=0 tid=0x00007fd1e80c5800 nid=0x4fa7 waiting on condition [0x00007fd1f10a0000]
       java.lang.Thread.State: TIMED_WAITING (sleeping)
    	at java.lang.Thread.sleep(Native Method)
    	at service.test.HttpCmdWaitTest.execute(HttpCmdWaitTest.java:14)
    	at frame.Command.start(Command.java:29)
    	at frame.http.HttpCmd.start(HttpCmd.java:26)
    	at frame.http.HttpHandler.handle(HttpHandler.java:34)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
    	at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:82)
    	at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:675)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
    	at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:647)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    	at java.lang.Thread.run(Thread.java:748)
    
    "pool-2-thread-8" #21 prio=5 os_prio=0 tid=0x00007fd1e80c4000 nid=0x4f97 waiting on condition [0x00007fd1f10e1000]
       java.lang.Thread.State: TIMED_WAITING (sleeping)
    	at java.lang.Thread.sleep(Native Method)
    	at service.test.HttpCmdWaitTest.execute(HttpCmdWaitTest.java:14)
    	at frame.Command.start(Command.java:29)
    	at frame.http.HttpCmd.start(HttpCmd.java:26)
    	at frame.http.HttpHandler.handle(HttpHandler.java:34)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
    	at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:82)
    	at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:675)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
    	at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:647)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    	at java.lang.Thread.run(Thread.java:748)
    
    "pool-2-thread-7" #20 prio=5 os_prio=0 tid=0x00007fd1e8080800 nid=0x4f94 waiting on condition [0x00007fd1f1122000]
       java.lang.Thread.State: TIMED_WAITING (sleeping)
    	at java.lang.Thread.sleep(Native Method)
    	at service.test.HttpCmdWaitTest.execute(HttpCmdWaitTest.java:14)
    	at frame.Command.start(Command.java:29)
    	at frame.http.HttpCmd.start(HttpCmd.java:26)
    	at frame.http.HttpHandler.handle(HttpHandler.java:34)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
    	at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:82)
    	at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:675)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
    	at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:647)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    	at java.lang.Thread.run(Thread.java:748)
    
    "pool-2-thread-6" #19 prio=5 os_prio=0 tid=0x00007fd1e80c2000 nid=0x4f91 waiting on condition [0x00007fd1f1163000]
       java.lang.Thread.State: TIMED_WAITING (sleeping)
    	at java.lang.Thread.sleep(Native Method)
    	at service.test.HttpCmdWaitTest.execute(HttpCmdWaitTest.java:14)
    	at frame.Command.start(Command.java:29)
    	at frame.http.HttpCmd.start(HttpCmd.java:26)
    	at frame.http.HttpHandler.handle(HttpHandler.java:34)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
    	at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:82)
    	at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:675)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
    	at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:647)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    	at java.lang.Thread.run(Thread.java:748)
    
    "pool-2-thread-5" #18 prio=5 os_prio=0 tid=0x00007fd1e80c0000 nid=0x4f8e waiting on condition [0x00007fd1f11a4000]
       java.lang.Thread.State: TIMED_WAITING (sleeping)
    	at java.lang.Thread.sleep(Native Method)
    	at service.test.HttpCmdWaitTest.execute(HttpCmdWaitTest.java:14)
    	at frame.Command.start(Command.java:29)
    	at frame.http.HttpCmd.start(HttpCmd.java:26)
    	at frame.http.HttpHandler.handle(HttpHandler.java:34)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
    	at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:82)
    	at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:675)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
    	at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:647)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    	at java.lang.Thread.run(Thread.java:748)
    
    "pool-2-thread-4" #17 prio=5 os_prio=0 tid=0x00007fd1e80be000 nid=0x4f8d waiting on condition [0x00007fd1f11e5000]
       java.lang.Thread.State: TIMED_WAITING (sleeping)
    	at java.lang.Thread.sleep(Native Method)
    	at service.test.HttpCmdWaitTest.execute(HttpCmdWaitTest.java:14)
    	at frame.Command.start(Command.java:29)
    	at frame.http.HttpCmd.start(HttpCmd.java:26)
    	at frame.http.HttpHandler.handle(HttpHandler.java:34)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
    	at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:82)
    	at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:675)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
    	at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:647)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    	at java.lang.Thread.run(Thread.java:748)
    
    "pool-2-thread-3" #16 prio=5 os_prio=0 tid=0x00007fd1e80bc000 nid=0x4f8c waiting on condition [0x00007fd1f1226000]
       java.lang.Thread.State: TIMED_WAITING (sleeping)
    	at java.lang.Thread.sleep(Native Method)
    	at service.test.HttpCmdWaitTest.execute(HttpCmdWaitTest.java:14)
    	at frame.Command.start(Command.java:29)
    	at frame.http.HttpCmd.start(HttpCmd.java:26)
    	at frame.http.HttpHandler.handle(HttpHandler.java:34)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
    	at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:82)
    	at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:675)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
    	at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:647)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    	at java.lang.Thread.run(Thread.java:748)
    
    "pool-2-thread-2" #15 prio=5 os_prio=0 tid=0x00007fd1e80f9800 nid=0x4f86 waiting on condition [0x00007fd1f1267000]
       java.lang.Thread.State: TIMED_WAITING (sleeping)
    	at java.lang.Thread.sleep(Native Method)
    	at service.test.HttpCmdWaitTest.execute(HttpCmdWaitTest.java:14)
    	at frame.Command.start(Command.java:29)
    	at frame.http.HttpCmd.start(HttpCmd.java:26)
    	at frame.http.HttpHandler.handle(HttpHandler.java:34)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
    	at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:82)
    	at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:675)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
    	at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:647)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    	at java.lang.Thread.run(Thread.java:748)
    
    "pool-2-thread-1" #14 prio=5 os_prio=0 tid=0x00007fd1e802e800 nid=0x4f85 waiting on condition [0x00007fd1f12a8000]
       java.lang.Thread.State: TIMED_WAITING (sleeping)
    	at java.lang.Thread.sleep(Native Method)
    	at service.test.HttpCmdWaitTest.execute(HttpCmdWaitTest.java:14)
    	at frame.Command.start(Command.java:29)
    	at frame.http.HttpCmd.start(HttpCmd.java:26)
    	at frame.http.HttpHandler.handle(HttpHandler.java:34)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
    	at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:82)
    	at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:675)
    	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
    	at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:647)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    	at java.lang.Thread.run(Thread.java:748)
    
    "DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x00007fd21404b800 nid=0x4f5b waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "Thread-3" #11 prio=5 os_prio=0 tid=0x00007fd2141d2000 nid=0x4f65 runnable [0x00007fd204078000]
       java.lang.Thread.State: RUNNABLE
    	at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
    	at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
    	at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
    	at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
    	- locked <0x00000000f8191ae0> (a sun.nio.ch.Util$3)
    	- locked <0x00000000f8191a58> (a java.util.Collections$UnmodifiableSet)
    	- locked <0x00000000f8191380> (a sun.nio.ch.EPollSelectorImpl)
    	at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
    	at sun.net.httpserver.ServerImpl$Dispatcher.run(ServerImpl.java:352)
    	at java.lang.Thread.run(Thread.java:748)
    
    "server-timer" #10 daemon prio=5 os_prio=0 tid=0x00007fd2141d0000 nid=0x4f64 in Object.wait() [0x00007fd2040b9000]
       java.lang.Thread.State: TIMED_WAITING (on object monitor)
    	at java.lang.Object.wait(Native Method)
    	- waiting on <0x00000000f81a2ff8> (a java.util.TaskQueue)
    	at java.util.TimerThread.mainLoop(Timer.java:552)
    	- locked <0x00000000f81a2ff8> (a java.util.TaskQueue)
    	at java.util.TimerThread.run(Timer.java:505)
    
    "Service Thread" #7 daemon prio=9 os_prio=0 tid=0x00007fd21413e800 nid=0x4f62 runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "C1 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007fd21413b800 nid=0x4f61 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007fd21412d000 nid=0x4f60 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007fd21412a800 nid=0x4f5f runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007fd214101000 nid=0x4f5e in Object.wait() [0x00007fd21806d000]
       java.lang.Thread.State: WAITING (on object monitor)
    	at java.lang.Object.wait(Native Method)
    	- waiting on <0x00000000f8008ed0> (a java.lang.ref.ReferenceQueue$Lock)
    	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
    	- locked <0x00000000f8008ed0> (a java.lang.ref.ReferenceQueue$Lock)
    	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
    	at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)
    
    "Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007fd2140fc800 nid=0x4f5d in Object.wait() [0x00007fd2180ae000]
       java.lang.Thread.State: WAITING (on object monitor)
    	at java.lang.Object.wait(Native Method)
    	- waiting on <0x00000000f8006bf8> (a java.lang.ref.Reference$Lock)
    	at java.lang.Object.wait(Object.java:502)
    	at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
    	- locked <0x00000000f8006bf8> (a java.lang.ref.Reference$Lock)
    	at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
    
    "VM Thread" os_prio=0 tid=0x00007fd2140f2800 nid=0x4f5c runnable 
    
    "VM Periodic Task Thread" os_prio=0 tid=0x00007fd214141000 nid=0x4f63 waiting on condition 
    
    JNI global references: 11
    
    上記のプロセス情報を分析すると、at service.test.HttpCmdWaitTest.execute(HttpCmdWaitTest.java:14)は9回も現れました。確かにこの異常インターフェースは9回も渋滞しました。残りはこのインターフェースの問題を分析します。もちろんここの間違いの原因はここでわざと書いた死循環です。
    ここでは単にjstackでスレッド情報を印刷することを紹介していますが、jvisualvm、jConsolieなどの機能的な使い方はここでは紹介しません。jvmについては、jvmのプロセス情報をチェックするツールを紹介しています。
    キャッシュスレッド池newCachedThreadPoolスレッド数が増加してメモリがオーバーフローします。
    固定長さスレッド池newFixedThreadPoolが要求に応じられないことを紹介しました。
    固定長スレッド池のスレッド数が限られている以上、実際のプロジェクトにはいくつかのインターフェースが存在して処理すると確実に時間がかかります。複数の処理が遅いインターフェース要求によって固定スレッドが占有され、後続のインターフェースが待ち時間が超過しても応答がないという問題が発生しやすいです。
    固定スレッド池をキャッシュスレッド池に変更できますか?この長さ制限はありません。
    このように簡単に変更することはできません。固定長のスレッド池をキャッシュスレッドに変更すると、また別のピットにジャンプします。キャッシュスレッド池はシステム全体に割り当てられた空間が足りなくなり、新しいスレッドを作成するとメモリが溢れてしまいます。
    一番いい解決方法は時間がかかりすぎるインターフェースを最適化することで時間が短縮されます。どうしてもだめなら、メッセージ・キューを使って、時間のかかる操作をキューに入れて、順番に取り出して実行する方法もあります。具体的な操作はどのように定義するべきですか?
    最後に、要求処理を提供するサービス(上のHttpServerサービスなど)について、スレッド池の選択について
    個人的には(私が見ている多くの項目の中にサービスを提供する要求があるのは全部固定長のスレッド池です。)それとも固定スレッド池を使ったほうがいいと思います。もちろん絶対というわけではないです。やはり実際のプロジェクトの必要性を見ます。固定長スレッド池とキャッシュスレッド池の機能特徴を本当に上手に把握してこそ、自分のプロジェクトに対するニーズが明確になり、どうやって選択すればいいのかが分かります。