スレッド プールの原理は次のとおりです。
手順:
現在実行中のスレッドの数が corePoolSize 未満の場合は、タスクを実行するための新しいスレッドを作成します。
実行中のスレッドが corePoolSize 以上の場合、タスクはキューに追加されます。
タスク キューがいっぱいになると、タスクを処理するために非コアプールに新しいスレッドが作成されます。
新しいスレッドを作成すると、現在実行中のスレッドが MaximumPoolSize を超え、タスクが拒否され、RejectedExecutionHandler.rejectedExecution() メソッドが呼び出されます。
スレッド プールには、CallerRunsPolicy、AbortPolicy、DiscardPolicy、DiscardOldestPolicy
public static class AbortPolicy implements RejectedExecutionHandler { public AbortPolicy() { } public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString()); } }
public class ThreadPoolTest { public static void main(String[] args) { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 2, 5, 10, TimeUnit.MICROSECONDS, new LinkedBlockingDeque<>(1), new ThreadPoolExecutor.AbortPolicy()); //异步执行 for(int i=0; i<10;i++) { System.out.println("添加第"+i+"个任务"); threadPoolExecutor.execute(new TestThread("线程"+i)); } } } public class TestThread implements Runnable { private String name; public TestThread(String name){ this.name=name; } @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("thread name:"+Thread.currentThread().getName()+",执行:"+name); } }
スレッド「メイン」の例外 java.util.concurrent.RejectedExecutionException: タスク com.skywares.fw.juc .thread.TestThread@55f96302 が java.util.concurrent.ThreadPoolExecutor@3d4eac69[実行中、プール サイズ = 5、アクティブ スレッド = 5、キューに入れられたタスク = 1、完了したタスク = 0]実行結果から、 AbortPolicy 戦略を使用すると、タスクが 7 番目のタスクに実行されるときにエラーが直接報告され、後続のビジネス ロジックは実行されません。 CallerRunsPolicyタスクが拒否された後、CallerRunsPolicy は、実行関数を呼び出す上位スレッドを使用して、拒否されたタスクを実行します。 関連例から拒否されました。 ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
で java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
で java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java: 1369)
com.skywares.fw.juc.thread.ThreadPoolTest.main(ThreadPoolTest.java:26)
スレッド名:pool-1-thread-5、実行: スレッド 5
スレッド名:プール-1-スレッド-2、実行: スレッド 1
スレッド名: プール-1-スレッド-4、実行: スレッド 4
スレッド名: プール-1-スレッド-3、実行: スレッド 3
スレッド名: pool-1-thread-1、実行: スレッド 0
スレッド名: pool-1-thread-5、実行: スレッド 2
public class ThreadPoolTest { public static void main(String[] args) { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 2, 5, 10, TimeUnit.MICROSECONDS, new LinkedBlockingDeque<>(1), new ThreadPoolExecutor.CallerRunsPolicy()); //异步执行 for(int i=0; i<10;i++) { System.out.println("添加第"+i+"个任务"); threadPoolExecutor.execute(new TestThread("线程"+i)); } } }
0 番目のタスクを追加実行結果から、7 番目のタスクが実行されると、スレッド プールの拒否ポリシーにより、このタスクはスレッド プールがアイドル状態のとき、メイン スレッドやその他のタスクは実行され続けます。1 番目のタスクを追加
2 番目のタスクを追加
3 番目のタスク
4 番目のタスクを追加
5 番目のタスクを追加
6 番目のタスクを追加
スレッド名:main、実行:スレッド 6
スレッド名:pool-1-thread-3、実行: スレッド 3
スレッド名: pool-1-thread-1、実行: スレッド 0
スレッド名: pool-1-thread-4、実行: スレッド 4
スレッド名:pool-1-thread -2、実行: スレッド 1
スレッド名: pool-1-thread-5、実行: スレッド 5
7 番目のタスクを追加
8 番目のタスクを追加
スレッド名:メイン、実行:スレッド8
スレッド名:pool-1-thread-1,execution:thread 7
thread name:pool-1-thread-3,execution:thread 2
9 番目のタスクを追加
スレッド名: pool-1-thread-1、実行: スレッド 9
したがって、この戦略はメインスレッドをブロックする可能性があります。
DiscardPolicyこの拒否ポリシーは比較的単純です。スレッド プールによって拒否されたタスクは、例外をスローしたり、Example を実行したりせずに、直接破棄されます。上記のコードを変更し、拒否ポリシーを DiscardPolicyThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 2, 5, 10, TimeUnit.MICROSECONDS, new LinkedBlockingDeque<>(1), new ThreadPoolExecutor.CallerRunsPolicy());
goodsId:mobilephonethread name:pool-1- thread- に変更します。 1、実行: スレッド 0
実行結果から判断すると、6 つのタスクのみが実行され、他のタスクは放棄されました。
スレッド名: プール-1-スレッド-4、実行: スレッド 4
スレッド名: プール-1-スレッド-5、実行: スレッド 5
スレッド名: プール- 1-スレッド-3、実行: スレッド 3
スレッド名: プール-1-スレッド-2、実行: スレッド 1
スレッド名: プール-1-スレッド-1、実行: スレッド 2
DiscardOldestPolicy
記述例
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 2, 10, TimeUnit.MICROSECONDS, new LinkedBlockingDeque<>(2), new ThreadPoolExecutor.CallerRunsPolicy());
1番目のタスクを追加2番目のタスクを追加
3 番目のタスク
4 番目のタスクを追加
5 番目のタスクを追加
dealStock の成功を呼び出す
goodsId: 携帯電話
スレッド名:pool-1-thread-2、実行: Thread 3
スレッド名:pool-1-thread-1、実行:スレッド 0
スレッド名:pool-1-thread-1、実行:スレッド 2
スレッド名:pool-1-thread- 2. 実行:スレッド1
当线程池提供的拒绝策略无法满足要求时,我们可以采用自定义的拒绝策略,只需要实现RejectedExecutionHandler接口即可
public class CustRejectedExecutionHandler implements RejectedExecutionHandler { @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { new Thread(r,"线程:"+new Random().nextInt(10)).start(); } } ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 2, 10, TimeUnit.MICROSECONDS, new LinkedBlockingDeque<>(2), new CustRejectedExecutionHandler());
执行结果:
thread name:客户线程:6,执行:线程5
thread name:pool-1-thread-1,执行:线程0
thread name:客户线程:8,执行:线程4
thread name:pool-1-thread-2,执行:线程3
thread name:pool-1-thread-1,执行:线程1
thread name:pool-1-thread-2,执行:线程2
从执行的结果来看,被拒绝的任务都在客户的新线程中执行。
AbortPolicy:直接抛出异常,后续的任务不会执行
CallerRunsPolicy:子任务执行的时间过长,可能会阻塞主线程。
DiscardPolicy:不抛异常,任务直接丢弃
DiscardOldestPolicy;丢弃最先加入队列的任务
以上がJava ThreadPoolExecutor の拒否ポリシーを実装するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。