Javaスレッドプールタスクの実行後にスレッドを回収

20477 ワード

Javaスレッドプールタスクの実行後にスレッドを回収
スレッドプール内のすべてのタスクが実行されると、スレッドは停止せず、JVMにOOMの問題が発生します.その後、次のリンクの資料を探して、問題を解決しました.ref: http://www.cnblogs.com/pengineer/p/5011965.html
問題と現象:
   public static void main(String[] args) {
   	BlockingQueue queue = new LinkedBlockingQueue();
   	ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 6, 10, TimeUnit.SECONDS, queue);
   	for (int i = 0; i < 20; i++) {
   		executor.execute(new Runnable() {
   			@Override
   			public void run() {
   				try {
   					System.out.println(this.hashCode() / 1000);
   					for (int j = 0; j < 10; j++) {
   						System.out.println(this.hashCode() + ":" + j);
   						Thread.sleep(this.hashCode() % 2);
   					}
   				} catch (InterruptedException e) {
   					e.printStackTrace();
   				}
   				System.out.println(String.format("thread %d finished", this.hashCode()));
   			}
   		});
   	}
   }

Java线程池任务执行完毕后回收线程_第1张图片タスクは完了しましたが、スレッドプール内のスレッドは回収されず、プログラムは実行中です.しかし、ThreadPoolExecutorのパラメータにタイムアウト時間が設定されているのは、ワークスレッドの回収には3つの条件を満たす必要があるため、役に立たないようです.
  • パラメータallowCoreThreadTimeOutはtrue
  • このスレッドはkeepAliveTime時間内にタスクを取得できない、すなわち、こんなに長い時間空いている
  • である.
  • 現在のスレッドプールサイズ>コアスレッドプールサイズcorePoolSize.

  • 解決1:allowCoreThreadTimeOutをtrueに設定
          public static void method1() {
              BlockingQueue queue = new LinkedBlockingQueue();
              ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 6, 1, TimeUnit.SECONDS, queue);  
              executor.allowCoreThreadTimeOut(true);
              for ( int i = 0; i < 20; i++) {
                  executor.execute( new Runnable() {
                      public void run() {
                          try {
                               System. out.println( this.hashCode()/1000);
                                  for ( int j = 0; j < 10; j++) {
                                    System. out.println( this.hashCode() + ":" + j);
                                    Thread. sleep(this.hashCode()%2);
                               } 
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                          System. out.println(String. format("thread %d finished", this.hashCode()));
                      }
                  });
              }
          }
    

    注意しなければならないのは、allowCoreThreadTimeOutの設定は、タスクの実行前に、一般的にnewのスレッドプールの後に設定する必要があります.allowCoreThreadTimeOutがtrueに設定されている場合、ThreadPoolExecutorのkeepAliveTimeパラメータは0より大きくなければなりません.
    解決2:shutdownメソッドの呼び出し
         public static void method1() {
              BlockingQueue queue = new LinkedBlockingQueue();
              ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 6, 1, TimeUnit.SECONDS, queue);
              for ( int i = 0; i < 20; i++) {
                  executor.execute( new Runnable() {
                      public void run() {
                          try {
                              System. out.println( this.hashCode()/1000);
                                for ( int j = 0; j < 10; j++) {
                                   System. out.println( this.hashCode() + ":" + j);
                                   Thread. sleep(this.hashCode()%2);
                              } 
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                          System. out.println(String. format("thread %d finished", this.hashCode()));
                      }
                  });
              }         
              executor.shutdown();
          }
    

    タスクの実行が完了したら、shutdownメソッドを呼び出し、スレッドプール内の空きスレッドを回収します.この方法はkeepAliveTimeパラメータを無効にする.