JDK並発注中のスレッドプール(一)
スレッドプールを使用しない場合の問題点
public class NonePool {
public static void main(String[] args) {
new Thread(){
public void run() {
//TODO
};
}.start();
}
}
上のコードは1つのスレッドを新設して、スレッドが終わる時、スレッドは自動的に生産環境の中でいくつかのスレッドを作成してシステムの機能を完成する必要があるかもしれなくて、必要なスレッドの数が多い時大量のスレッドを割り当てる必要があって、このような方法を使うと以下の問題があります:1.大量のスレッドを作成するには大量のCPU 2を消費する必要がある.スレッド自体も大量のメモリとCPU 3を占有する必要がある.スレッドの実行が完了した後に回収する必要があって、回収する時大量のGC操作を必要として総合的に、システムの中で、スレッドの数量は多ければ多いほどシステムの性能を高めることができるのではありませんて、1つの限度が必要です
スレッドプール
頻繁なスレッドの作成とスレッドの破棄を避けるために、作成したスレッドをデータベース接続プールと同様に多重化できます.
JDKでサポートされているスレッドプール
スレッドプールのケーススタディ
newFixedThreadPool
public class FixedThreadPool {
public static void main(String[] args) {
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
for(int i=0;i<10;i++){
fixedThreadPool.submit(new MyTask(i));
}
}
}
class MyTask implements Runnable{
private int i;
public MyTask(int i) {
super();
this.i = i;
}
@Override
public void run() {
System.out.println(new Date().getTime()+"___"+Thread.currentThread().getId()+"___"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
1497167121692___13___4
1497167121692___10___1
1497167121692___11___2
1497167121692___12___3
1497167121692___9___0
1497167122692___13___5
1497167122692___9___6
1497167122693___10___7
1497167122694___11___8
1497167122694___12___9
解析:第1のバッチの実行時間は14971671121692であり、第2のバッチの5つは14971671122692であり、前の5つの実行スレッドのidは後の5つと同じであり、確かに5つのスレッドが作成され、多重化できることを証明している.
newScheduledThreadPool
scheduleAtFixedRate
public class ScheduledThreadPool {
public static void main(String[] args) {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10);
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getId()+"\tbegin\t"+System.currentTimeMillis());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getId()+"\tend\t"+System.currentTimeMillis());
}
}, 0, 2, TimeUnit.SECONDS);
}
}
public ScheduledFuture
9 begin 1497178292150
9 end 1497178293151
9 begin 1497178294151
9 end 1497178295152
11 begin 1497178296151
11 end 1497178297151
9 begin 1497178298151
9 end 1497178299151
各タスクにかかる時間がperiodより大きい場合は、どうすればいいですか?上記のタスクのスリープ1 sをスリープ8 sに変更すると、次のようになります.
9 begin 1497178511226
9 end 1497178519227
9 begin 1497178519227
9 end 1497178527228
11 begin 1497178527229
11 end 1497178535229
9 begin 1497178535229
9 end 1497178543229
このとき、後続の第1のタスクを実行する(1回目は実行しない)時間はinitialDelay+8 sであり、後続の第2のタスクを実行する時間はinitialDelay+2*8 sであることがわかる.つまり、同じ時点で1つのタスクしか実行されず、実行するサイクルはタスクにかかる時間とサイクルの大きさの間で大きな値をとる
scheduleWithFixedDelay
同じ上のコードで、scheduledAtFixedRateをscheduleWithFixedDelayに変更すると、後続のタスクが前のタスクの実行が完了した後にperiod時間で実行され、上のプログラムの実行結果は
9 begin 1497178896324
9 end 1497178897324
9 begin 1497178899324
9 end 1497178900325
11 begin 1497178902326
11 end 1497178903326
9 begin 1497178905327
9 end 1497178906327
各タスクの開始は、前のタスクが終了してから2秒で実行されることがわかります.