Java concurrencyスレッド池のスレッド池原理(四)_動力ノードJava学院の整理


ポリシーの紹介を拒否します
スレッドプールの拒否戦略とは、スレッドプールにジョブが追加されたときに拒否された場合の処理です。
スレッドプールにジョブが追加されたときに拒否されたのは、第一に、スレッドが異常に停止したためです。第二に、スレッド池の最大制限を超えたジョブの数。
スレッドプールには4つの拒否戦略が含まれています。それぞれはAbortPolicyです。 CallerRuns Policy、 Discard Oldest PolicyとDiscrdPolicy。
  • AbortPolicy         -- タスクをスレッドに追加すると拒否された場合、RejectedExecution Exception異常をスローします。
  • CallerRunsPolicy    -- タスクがスレッドに追加されて拒否された場合、現在実行中のThreadスレッドプールで拒否されたタスクを処理します。
  • DisccardOldest Policy--ジョブがスレッドプールに追加されて拒否されると、スレッド池は待ち行列の中で最も古い未処理タスクを放棄し、拒否されたジョブを待ち行列に追加する。
  • DisccardPolicy       -- スレッドプールにジョブを追加すると拒否された場合、スレッドプールは拒否されたタスクを破棄します。
  • スレッドのデフォルトの処理戦略は、AbortPolicyです。
    拒否戦略の比較と例
    以下では、一例を通して、スレッドプールの4つの拒否戦略を示します。
    1.DiscrdPolicyの例
    
     import java.lang.reflect.Field;
     import java.util.concurrent.ArrayBlockingQueue;
     import java.util.concurrent.ThreadPoolExecutor;
     import java.util.concurrent.TimeUnit;
     import java.util.concurrent.ThreadPoolExecutor.DiscardPolicy;
     
     public class DiscardPolicyDemo {
     
       private static final int THREADS_SIZE = 1;
       private static final int CAPACITY = 1;
     
       public static void main(String[] args) throws Exception {
     
         //      。    "     " "     "  1(THREADS_SIZE),"   "        1(CAPACITY)。
         ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS,
             new ArrayBlockingQueue<Runnable>(CAPACITY));
         //            "  "
         pool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
     
         //   10   ,           。
         for (int i = 0; i < 10; i++) {
           Runnable myrun = new MyRunnable("task-"+i);
           pool.execute(myrun);
         }
         //      
         pool.shutdown();
       }
     }
     
     class MyRunnable implements Runnable {
       private String name;
       public MyRunnable(String name) {
         this.name = name;
       }
       @Override
       public void run() {
         try {
           System.out.println(this.name + " is running.");
           Thread.sleep(100);
         } catch (Exception e) {
           e.printStackTrace();
         }
       }
     }
    
    
    実行結果:
    
    task-0 is running.
    task-1 is running.
    スレッドプールプールのpoolの「最大プールサイズ」と「コアプールサイズ」はいずれも1です。SIZE)とは、「スレッドが同時に動作するジョブの数は最大で1しかない」という意味です。
    スレッドプールのブロック列はArayBlockingQueで、ArayBlockingQueは境界があるブロック列で、ArayBlocking Queの容量は1です。これはまた、スレッド池のブロック列はスレッドプールが一つしかないことを意味します。
    「」で分析したexecuteコードによると、スレッド池では2つのタスクが実行されています。第1のタスクは直接Workカーに置いて、スレッドで実行します。2番目のタスクはブロック列で待機します。他のミッションは全部破棄されました。
    2.DiscrdOldest Policyの例
    
     import java.lang.reflect.Field;
     import java.util.concurrent.ArrayBlockingQueue;
     import java.util.concurrent.ThreadPoolExecutor;
     import java.util.concurrent.TimeUnit;
     import java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy;
     
     public class DiscardOldestPolicyDemo {
     
       private static final int THREADS_SIZE = 1;
       private static final int CAPACITY = 1;
     
       public static void main(String[] args) throws Exception {
     
         //      。    "     " "     "  1(THREADS_SIZE),"   "        1(CAPACITY)。
         ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS,
             new ArrayBlockingQueue<Runnable>(CAPACITY));
         //            "DiscardOldestPolicy"
         pool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
     
         //   10   ,           。
         for (int i = 0; i < 10; i++) {
           Runnable myrun = new MyRunnable("task-"+i);
           pool.execute(myrun);
         }
         //      
         pool.shutdown();
       }
     }
     
     class MyRunnable implements Runnable {
       private String name;
       public MyRunnable(String name) {
         this.name = name;
       }
       @Override
       public void run() {
         try {
           System.out.println(this.name + " is running.");
           Thread.sleep(200);
         } catch (Exception e) {
           e.printStackTrace();
         }
       }
     }
    
    
    実行結果:
    
    task-0 is running.
    task-9 is running.
    その結果、「スレッド池の拒否戦略」をDisc PolicyからDiscrdOldest Policyに変更した後、スレッドプールにジョブが追加されて拒否されると、スレッドプールはブロック列の最後のタスクを破棄し、拒否されたタスクを最後に追加します。 
    3.AbortPolicy例
    
     import java.lang.reflect.Field;
     import java.util.concurrent.ArrayBlockingQueue;
     import java.util.concurrent.ThreadPoolExecutor;
     import java.util.concurrent.TimeUnit;
     import java.util.concurrent.ThreadPoolExecutor.AbortPolicy;
     import java.util.concurrent.RejectedExecutionException;
     
     public class AbortPolicyDemo {
     
       private static final int THREADS_SIZE = 1;
       private static final int CAPACITY = 1;
     
       public static void main(String[] args) throws Exception {
     
         //      。    "     " "     "  1(THREADS_SIZE),"   "        1(CAPACITY)。
         ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS,
             new ArrayBlockingQueue<Runnable>(CAPACITY));
         //            "    "
         pool.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
     
         try {
     
           //   10   ,           。
           for (int i = 0; i < 10; i++) {
             Runnable myrun = new MyRunnable("task-"+i);
             pool.execute(myrun);
           }
         } catch (RejectedExecutionException e) {
           e.printStackTrace();
           //      
           pool.shutdown();
         }
       }
     }
     
     class MyRunnable implements Runnable {
       private String name;
       public MyRunnable(String name) {
         this.name = name;
       }
       @Override
       public void run() {
         try {
           System.out.println(this.name + " is running.");
           Thread.sleep(200);
         } catch (Exception e) {
           e.printStackTrace();
         }
       }
     }
    
    
    (ある時)運転結果:
    
    java.util.concurrent.RejectedExecutionException
      at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1774)
      at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:768)
      at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:656)
      at AbortPolicyDemo.main(AbortPolicyDemo.java:27)
    task-0 is running.
    task-1 is running.
    その結果、「スレッド池の拒否戦略」をDisc PolicyからAbortPolicyに変更した後、スレッド池にジョブが追加されて拒否された場合、RejectedExecution Exceptionをスローします。
    4.CallerRuns Policy例
    
     import java.lang.reflect.Field;
     import java.util.concurrent.ArrayBlockingQueue;
     import java.util.concurrent.ThreadPoolExecutor;
     import java.util.concurrent.TimeUnit;
     import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
     
     public class CallerRunsPolicyDemo {
     
       private static final int THREADS_SIZE = 1;
       private static final int CAPACITY = 1;
     
       public static void main(String[] args) throws Exception {
     
         //      。    "     " "     "  1(THREADS_SIZE),"   "        1(CAPACITY)。
         ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS,
             new ArrayBlockingQueue<Runnable>(CAPACITY));
         //            "CallerRunsPolicy"
         pool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
     
         //   10   ,           。
         for (int i = 0; i < 10; i++) {
           Runnable myrun = new MyRunnable("task-"+i);
           pool.execute(myrun);
         }
     
         //      
         pool.shutdown();
       }
     }
     
     class MyRunnable implements Runnable {
       private String name;
       public MyRunnable(String name) {
         this.name = name;
       }
       @Override
       public void run() {
         try {
           System.out.println(this.name + " is running.");
           Thread.sleep(100);
         } catch (Exception e) {
           e.printStackTrace();
         }
       }
     }
    
    
    (ある時)運転結果:
    
    task-2 is running.
    task-3 is running.
    task-4 is running.
    task-5 is running.
    task-6 is running.
    task-7 is running.
    task-8 is running.
    task-9 is running.
    task-0 is running.
    task-1 is running.
    
    
    その結果、「スレッド池の拒否戦略」をDisc PolicyからCaller RunsPolicyに変更した後、スレッドプールにジョブが追加されて拒否された場合、スレッド池は拒否されたジョブを「スレッド池が実行中のスレッド」に追加して実行をとることができる。