Javaスレッドプールの学習
本文はjavaスレッドプールクラスThreadPoolExecutorに対する学習を開くつもりで、スレッドプールはjavaスレッドクラスライブラリの中でとても核心的な内容で、高級進級は必見の内容に属して、簡単にThreadPoolExecutorが実現関係を継承することを見ます:
ThreadPoolExecutorクラスはjava.util.concurrentの下にあり、ThreadPoolExecutorは抽象クラスAbstractExecutorServiceに継承され、AbstractExecutorService抽象はまたインタフェースクラスExecutorServiceの方法を実現し、インタフェースクラスExecutorServiceはインタフェースクラスExecutorを継承している.
Executor
public interface Executor {
/**
* Executes the given command at some time in the future. The command
* may execute in a new thread, in a pooled thread, or in the calling
* thread, at the discretion of the {@code Executor} implementation.
*
* @param command the runnable task
* @throws RejectedExecutionException if this task cannot be
* accepted for execution
* @throws NullPointerException if command is null
*/
void execute(Runnable command);
}
このクラスには特に何もありません.説明からexecuteという方法を見て、将来のある時に与えられたコマンドを実行します.このコマンドは、Executorという関数によって決定される新しいスレッド、プール化スレッド、または呼び出しスレッドで実行できます.また,このタスクが受け入れられない場合にはRejectedExecutionException異常を投げ出す必要があり,実行するタスクが空(commandパラメータ内容)の場合にはNull PointerExceptionという異常を投げ出す.
簡単に言えば、このインタフェースのタスクは特定のタスクを実行することであり、このタスクをどのように実行するかは、新しいスレッドを作成するか、スレッドプールから取得したスレッドをどのように実行するかは、彼のクラスを実装することによって決定されます.また,特定の場合にはRejectedExecutionException異常とNull PointerException異常を投げ出す必要がある.
ExecutorService
ExecutorServiceはインタフェースクラスで、Executorを継承し、12の新しいメソッドを追加しました.抽象クラスAbstractExecutorServiceは最終的にExecutorServiceの一部のインタフェースを実現し、同時にThreadPoolExecutorは抽象クラスを継承し、未実現のインタフェースを実現した.
void shutdown();
List<Runnable> shutdownNow();
boolean isShutdown();
boolean isTerminated();
boolean awaitTermination(long timeout, TimeUnit unit)throws InterruptedException;
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)throws InterruptedException;
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,long timeout, TimeUnit unit)throws InterruptedException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks)throws InterruptedException, ExecutionException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks,long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException;
void shutdown()
メソッド記述の原話は,著者らがこのインタフェースを実装したい内容を示す.
/**
* Initiates an orderly shutdown in which previously submitted
* tasks are executed, but no new tasks will be accepted.
* Invocation has no additional effect if already shut down.
*
* This method does not wait for previously submitted tasks to
* complete execution. Use {@link #awaitTermination awaitTermination}
* to do that.
*
* @throws SecurityException if a security manager exists and
* shutting down this ExecutorService may manipulate
* threads that the caller is not permitted to modify
* because it does not hold {@link
* java.lang.RuntimePermission}{@code ("modifyThread")},
* or the security manager's {@code checkAccess} method
* denies access.
*/
void shutdown();
List shutdownNow()
/**
* Attempts to stop all actively executing tasks, halts the
* processing of waiting tasks, and returns a list of the tasks
* that were awaiting execution.
*
* This method does not wait for actively executing tasks to
* terminate. Use {@link #awaitTermination awaitTermination} to
* do that.
*
*
There are no guarantees beyond best-effort attempts to stop
* processing actively executing tasks. For example, typical
* implementations will cancel via {@link Thread#interrupt}, so any
* task that fails to respond to interrupts may never terminate.
*
* @return list of tasks that never commenced execution
* @throws SecurityException if a security manager exists and
* shutting down this ExecutorService may manipulate
* threads that the caller is not permitted to modify
* because it does not hold {@link
* java.lang.RuntimePermission}{@code ("modifyThread")},
* or the security manager's {@code checkAccess} method
* denies access.
*/
List<Runnable> shutdownNow();
awaitTermination(long timeOut, TimeUnit unit)
/**
* Returns {@code true} if all tasks have completed following shut down.
* Note that {@code isTerminated} is never {@code true} unless
* either {@code shutdown} or {@code shutdownNow} was called first.
*
* @return {@code true} if all tasks have completed following shut down
*/
boolean isTerminated();
コードの例
public static void main(String[] args) {
// 5
ExecutorService pool = Executors.newFixedThreadPool(5);
// 1
Runnable r1 = new Runnable() {
@Override
public void run() {
try {
System.out.println("start r1 job..");
Thread.sleep(1*1000);
}catch (InterruptedException e){
System.out.println("r1 interrupted:"+e.getMessage());
}
}
};
// 10
Runnable r2 = new Runnable() {
@Override
public void run() {
try {
System.out.println("start r2 job..");
Thread.sleep(10 * 1000);
}catch (InterruptedException e){
System.out.println("r2 interrupted:"+e.getMessage());
}
}
};
//
Runnable r3 = new Runnable() {
@Override
public void run() {
while (true){ }
}
};
// //
// pool.execute(r1);
// //
// pool.execute(r2);
//
pool.execute(r3);
try {
// , , , 。
pool.shutdown();
// shutdown , ,
if(!pool.awaitTermination(5, TimeUnit.SECONDS)){
// 5 ,
// 5 ,awaitTermination false, 。
// shutdownNow
pool.shutdownNow();
if(!pool.awaitTermination(2,TimeUnit.SECONDS)){
// shutdownNow , 2 。
// false, shutdownNow ,
System.out.println(" , ");
}
}else{
System.out.println(" ");
}
}catch (InterruptedException e){
System.out.println("awaitTermination interrupted: " + e);
// , 。 , ,
System.out.println(" ");
pool.shutdownNow();
}
}
このコードでは、スレッドプールを使用するいくつかの状況を示します.
3つ目の解決策について、ここで公式を調べてみましたが、具体的にどのように解決するかはあまり言われていませんが、これは悪い書き方のはずです.
公式ドキュメントアドレス
What if a thread doesn't respond to Thread.interrupt?
In some cases, you can use application specific tricks. For example, if a thread is waiting on a known socket, you can close the socket to cause the thread to return immediately. Unfortunately, there really isn't any technique that works in general. It should be noted that in all situations where a waiting thread doesn't respond to Thread.interrupt, it wouldn't respond to Thread.stop either. Such cases include deliberate denial-of-service attacks, and I/O operations for which thread.stop and thread.interrupt do not work properly.
他の資料を調べてみると
shutdownNowメソッドの役割は、すべての実行中のスレッドにinterruptedを発行してスレッドの実行を中止することです.このとき,各スレッドはInterruptedException異常を放出する(スレッドでsleepなどの異常を放出する方法が実行されていることを前提とする).r 3のタスクメソッドを使用しなければならない場合は、このように修正することができます.
Runnable r3 = new Runnable() {
@Override
public void run() {
try {
while (true){
Thread.sleep(1);
}
}catch (InterruptedException e){
System.out.println("r3 interrupted:"+e.getMessage());
}
}
};
スレッドループの場合、毎回1ミリ秒停止します.このsleepの役割は、後のinterruptedがこのデッドループスレッドを終了させるためです.もちろんこれはやむを得ずですが、書き方でもwhile(true)はお勧めしませんので、条件結果を判断することで運転を続けるかどうかを決めるのが望ましいです.たとえば
Runnable r3 = new Runnable() {
@Override
public void run() {
int i = 0;
while (i<10){
i++;
}
}
};
要するにスレッドを用いてタスクを実行する場合は,慎重な処理が必要である.スレッドデッドサイクル、最大のデメリットは、cpuの使用率が増加し、他のスレッドと競合するリソース現象があれば、デッドロックの可能性が高いことです.また、jvmスタックのメモリが上昇し続け、full gcの周波数が増加し、最終的にスタックがオーバーフローした場合、スレッドが終了したり、OOMが発生したりする可能性があります.
未完待機