Java concurrencyスレッド池のスレッド池原理(四)_動力ノードJava学院の整理
9064 ワード
ポリシーの紹介を拒否します
スレッドプールの拒否戦略とは、スレッドプールにジョブが追加されたときに拒否された場合の処理です。
スレッドプールにジョブが追加されたときに拒否されたのは、第一に、スレッドが異常に停止したためです。第二に、スレッド池の最大制限を超えたジョブの数。
スレッドプールには4つの拒否戦略が含まれています。それぞれはAbortPolicyです。 CallerRuns Policy、 Discard Oldest PolicyとDiscrdPolicy。 AbortPolicy -- タスクをスレッドに追加すると拒否された場合、RejectedExecution Exception異常をスローします。 CallerRunsPolicy -- タスクがスレッドに追加されて拒否された場合、現在実行中のThreadスレッドプールで拒否されたタスクを処理します。 DisccardOldest Policy--ジョブがスレッドプールに追加されて拒否されると、スレッド池は待ち行列の中で最も古い未処理タスクを放棄し、拒否されたジョブを待ち行列に追加する。 DisccardPolicy -- スレッドプールにジョブを追加すると拒否された場合、スレッドプールは拒否されたタスクを破棄します。 スレッドのデフォルトの処理戦略は、AbortPolicyです。
拒否戦略の比較と例
以下では、一例を通して、スレッドプールの4つの拒否戦略を示します。
1.DiscrdPolicyの例
スレッドプールのブロック列はArayBlockingQueで、ArayBlockingQueは境界があるブロック列で、ArayBlocking Queの容量は1です。これはまた、スレッド池のブロック列はスレッドプールが一つしかないことを意味します。
「」で分析したexecuteコードによると、スレッド池では2つのタスクが実行されています。第1のタスクは直接Workカーに置いて、スレッドで実行します。2番目のタスクはブロック列で待機します。他のミッションは全部破棄されました。
2.DiscrdOldest Policyの例
3.AbortPolicy例
4.CallerRuns Policy例
スレッドプールの拒否戦略とは、スレッドプールにジョブが追加されたときに拒否された場合の処理です。
スレッドプールにジョブが追加されたときに拒否されたのは、第一に、スレッドが異常に停止したためです。第二に、スレッド池の最大制限を超えたジョブの数。
スレッドプールには4つの拒否戦略が含まれています。それぞれはAbortPolicyです。 CallerRuns Policy、 Discard Oldest PolicyとDiscrdPolicy。
拒否戦略の比較と例
以下では、一例を通して、スレッドプールの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に変更した後、スレッドプールにジョブが追加されて拒否された場合、スレッド池は拒否されたジョブを「スレッド池が実行中のスレッド」に追加して実行をとることができる。