ScheduledExecutorServiceは、タイミングおよび周期的なタスク実行をサポートする定長スレッドプールです.
6818 ワード
ScheduledExecutorServiceの主な役割は、タイミングタスクとスレッドプール機能を組み合わせて使用できることです.
スレッドプールに基づいて設計されたタイミングタスククラスであるため、各スケジューリングタスクはスレッドプール内のスレッドに割り当てられて実行されます.すなわち、タスクは同時実行であり、互いに影響しません.
スケジューリング・タスクが来た場合にのみ、ScheduledExecutorServiceはスレッドを実際に起動し、残りの時間はタスクをポーリングした状態であることに注意してください.
Executorsはファクトリモードを利用して4つのスレッドプールの実装方法を提供していますが、Executorsを使用してスレッドプールを作成するとこのパラメータが入力されずデフォルト値が使用されるため、このパラメータを無視することがよくあります.また、デフォルトで使用されるパラメータはリソースの浪費を引き起こし、望ましくありません.
numはスレッドプールでnum個のスレッドを同時に実行できるという意味ですが、スレッドプールでは永遠にこの3つのスレッドであるわけではありません.ただ、同時に存在できるスレッド数という意味で、あるスレッドの実行が終了すると、新しいスレッドが入ってきます.
daemon(true)はスレッドを守るという意味です
Javaにはユーザスレッド(User Thread)、デーモンスレッド(Daemon Thread)の2種類がある.
デーモンスレッドとは、プログラムの実行時にバックグラウンドで汎用サービスを提供するスレッドであり、例えばゴミ回収スレッドは非常に適任なデーモンであり、このようなスレッドはプログラムの不可欠な部分ではない.したがって、すべての非デーモンスレッドが終了すると、プログラムは終了し、プロセス内のすべてのデーモンスレッドを殺すことになります.逆に言えば、非デーモンスレッドがまだ実行されている限り、プログラムは終了しません.
ユーザー・スレッドとデーモン・スレッドの違いはほとんどありません.唯一の違いは、仮想マシンの離脱です.ユーザー・スレッドがすべて実行を終了した場合、デーモン・スレッドだけが存在し、仮想マシンも終了します.被守護者がいなければ,守護スレッドも仕事ができず,プログラムを実行し続ける必要もないからである.
スレッドをデーモンスレッドに変換することは、ThreadオブジェクトのsetDaemon(true)メソッドを呼び出すことによって実現することができる.デーモンスレッドを使用する場合は、次の点に注意してください.
(1) thread.setDaemon(true)はthread.start()の前に設定しないと、IllegalThreadStateException異常が飛び出します.実行中の通常のスレッドをデーモンスレッドに設定することはできません.
(2)Daemonスレッドで生成された新しいスレッドもDaemonである.
(3)デーモン・スレッドは、いつでも1つの操作の間で中断されるため、ファイル、データベースなどの固有のリソースにアクセスしないでください.
falseexecutorService.scheduleWithFixedDelay(command, initialDelay, delay, unit) falseexecutorService.scheduleAtFixedRate(command, initialDelay, period, unit) falseexecutorService.schedule(command, delay, unit)パラメータcommandメソッド実行体 パラメータinitialDelayが初めて実行する遅延時間 パラメータdelayタイミング実行間隔時間 パラメータunit単位
scheduleAtFixedRateサイクルタスクは厳格に5秒ごとに開始する.sleep(3000); ただし、前のスレッドへの影響複数のスレッドが次のスレッドの実行に影響しない場合-->以上のタスクの開始時間+遅延時間=次のタスクの開始時間です.
出力結果:
scheduleWithFixedDelayループタスクは厳格に1秒ごとに開始され、sleep(3000)はタスクの開始に影響を与える以上のタスクの終了時間+遅延時間=次のタスクの開始時間である.
出力結果:
scheduleは遅延タスクで1回のみ実行されます
実行結果:
スレッドプールに基づいて設計されたタイミングタスククラスであるため、各スケジューリングタスクはスレッドプール内のスレッドに割り当てられて実行されます.すなわち、タスクは同時実行であり、互いに影響しません.
スケジューリング・タスクが来た場合にのみ、ScheduledExecutorServiceはスレッドを実際に起動し、残りの時間はタスクをポーリングした状態であることに注意してください.
ScheduledExecutorServiceスレッドプールを作成するには、次の2つの方法があります。
1つ目はExecutorsで作成
Executorsはファクトリモードを利用して4つのスレッドプールの実装方法を提供していますが、Executorsを使用してスレッドプールを作成するとこのパラメータが入力されずデフォルト値が使用されるため、このパラメータを無視することがよくあります.また、デフォルトで使用されるパラメータはリソースの浪費を引き起こし、望ましくありません.
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
ScheduledExecutorService mScheduledExecutorService = Executors.newScheduledThreadPool(num);
numはスレッドプールでnum個のスレッドを同時に実行できるという意味ですが、スレッドプールでは永遠にこの3つのスレッドであるわけではありません.ただ、同時に存在できるスレッド数という意味で、あるスレッドの実行が終了すると、新しいスレッドが入ってきます.
第2の方法もアリコード規範が推奨している。
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,
1,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue());
ScheduledExecutorService newScheduledThreadPool =
Executors.newScheduledThreadPool(4,threadPoolExecutor.getThreadFactory());
//org.apache.commons.lang3.concurrent.BasicThreadFactory
ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,
new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());
ScheduledExecutorService falseexecutorService = new ScheduledThreadPoolExecutor(num);
daemon(true)はスレッドを守るという意味です
Javaにはユーザスレッド(User Thread)、デーモンスレッド(Daemon Thread)の2種類がある.
デーモンスレッドとは、プログラムの実行時にバックグラウンドで汎用サービスを提供するスレッドであり、例えばゴミ回収スレッドは非常に適任なデーモンであり、このようなスレッドはプログラムの不可欠な部分ではない.したがって、すべての非デーモンスレッドが終了すると、プログラムは終了し、プロセス内のすべてのデーモンスレッドを殺すことになります.逆に言えば、非デーモンスレッドがまだ実行されている限り、プログラムは終了しません.
ユーザー・スレッドとデーモン・スレッドの違いはほとんどありません.唯一の違いは、仮想マシンの離脱です.ユーザー・スレッドがすべて実行を終了した場合、デーモン・スレッドだけが存在し、仮想マシンも終了します.被守護者がいなければ,守護スレッドも仕事ができず,プログラムを実行し続ける必要もないからである.
スレッドをデーモンスレッドに変換することは、ThreadオブジェクトのsetDaemon(true)メソッドを呼び出すことによって実現することができる.デーモンスレッドを使用する場合は、次の点に注意してください.
(1) thread.setDaemon(true)はthread.start()の前に設定しないと、IllegalThreadStateException異常が飛び出します.実行中の通常のスレッドをデーモンスレッドに設定することはできません.
(2)Daemonスレッドで生成された新しいスレッドもDaemonである.
(3)デーモン・スレッドは、いつでも1つの操作の間で中断されるため、ファイル、データベースなどの固有のリソースにアクセスしないでください.
ScheduledExecutorServiceの方法
falseexecutorService.scheduleWithFixedDelay(command, initialDelay, delay, unit) falseexecutorService.scheduleAtFixedRate(command, initialDelay, period, unit) falseexecutorService.schedule(command, delay, unit)
// TimeUnit.NANOSECONDS
// TimeUnit.MICROSECONDS
// TimeUnit.MILLISECONDS
// TimeUnit.SECONDS
// TimeUnit.MINUTES
// TimeUnit.HOURS
// TimeUnit.DAYS
メソッドscheduleAtFixedRateループタスク
scheduleAtFixedRateサイクルタスクは厳格に5秒ごとに開始する.sleep(3000); ただし、前のスレッドへの影響複数のスレッドが次のスレッドの実行に影響しない場合-->以上のタスクの開始時間+遅延時間=次のタスクの開始時間です.
executorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("run {{"+Thread.currentThread().getName()+"}}> "
+ System.currentTimeMillis()/1000);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, 1, 5, //TimeUnit.MILLISECONDS
TimeUnit.SECONDS);
出力結果:
run {{pool-1-thread-1}}> 1551258899
run {{pool-1-thread-1}}> 1551258904
run {{pool-1-thread-2}}> 1551258909
メソッドscheduleWithFixedDelay遅延サイクルタスク
scheduleWithFixedDelayループタスクは厳格に1秒ごとに開始され、sleep(3000)はタスクの開始に影響を与える以上のタスクの終了時間+遅延時間=次のタスクの開始時間である.
executorService.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
System.out.println("run {{"+Thread.currentThread().getName()+"}}> "
System.currentTimeMillis()/1000);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, 0, 5, //TimeUnit.MILLISECONDS
TimeUnit.SECONDS);
出力結果:
run {{pool-1-thread-1}}> 1551259165
run {{pool-1-thread-1}}> 1551259173
run {{pool-1-thread-2}}> 1551259181
run {{pool-1-thread-1}}> 1551259189
run {{pool-1-thread-1}}> 1551259197
メソッドschedule遅延タスク
scheduleは遅延タスクで1回のみ実行されます
executorService.schedule((new Runnable() {
@Override
public void run() {
System.out.println("run >>>> "+ System.currentTimeMillis());
}
}), 3, TimeUnit.MILLISECONDS);
実行結果:
run >>>> 1551259382734