同時(5)-concurrentパッケージコンポーネント
3742 ワード
java.util.concurrentのコンポーネント
CountDownLatch
CountDownLatch
は、1つまたは複数のタスクを同期させ、タスクのセットの動作を強制するために使用される.public class Main {
static final int SIZE = 10;
public static void main(String[] args) throws InterruptedException, IOException {
ExecutorService exec = Executors.newCachedThreadPool();
CountDownLatch latch = new CountDownLatch(SIZE);
int count = 10;
while (count-- > 0) {
exec.execute(() -> {
try {
TimeUnit.MILLISECONDS.sleep(100);
System.out.println("one task was finished");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
latch.countDown();
}
});
}
exec.execute(() -> {
try {
latch.await();
System.out.println("submit tasks report");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
TimeUnit.MILLISECONDS.sleep(4000);
exec.shutdownNow();
}
}
one task was finished one task was finished one task was finished one task was finished one task was finished one task was finished one task was finished one task was finished one task was finished one task was finished submit tasks report CountDownLatch
オブジェクト上でawait()
メソッドを呼び出すタスクは、latchカウントが0になるまでブロックされます.CountDownLatch
は、一度しか使用できず、カウンタの値をリセットできないように設計されている.
CyclicBarrier
複数回再利用可能なCountDownLatch
.public class Main {
private static final int SIZE = 10;
private static Random random = new Random(47);
public static void main(String[] args) throws InterruptedException, IOException {
ExecutorService exec = Executors.newCachedThreadPool();
CyclicBarrier barrier = new CyclicBarrier(SIZE, () -> System.out.println("submit tasks report"));
int count = 10;
while (count-- > 0){
exec.execute(() -> {
try {
TimeUnit.MILLISECONDS.sleep(random.nextInt(1000));
System.out.println("one task was finished");
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
});
}
TimeUnit.MILLISECONDS.sleep(4000);
exec.shutdownNow();
}
}
CyclicBarrier
オブジェクトが呼び出されたawait()
回数、すなわち、このリソースを待ってブロックされたスレッド数が、このコンストラクタに設定された値に達すると、コンストラクタに入力されたRunnable()
メソッドが実行され、count値を20に変更すると、この「submit tasks report」が2回出力され、すなわち、我々が望む効果を達成することができる.
ScheduledExecutor
schedule()
(タスクを1回実行)またはscheduleAtFixedRate()
(ルールごとにタスクを繰り返し実行)を使用します.public class Main {
private static final int SIZE = 5;
private static Random random = new Random(47);
public static void main(String[] args) throws InterruptedException, IOException {
long start = System.currentTimeMillis();
ScheduledExecutorService service = Executors.newScheduledThreadPool(SIZE);
for (int i = 0; i < SIZE; i++) {
service.schedule(() -> System.out.println(System.currentTimeMillis() - start),
random.nextInt(3000), TimeUnit.MILLISECONDS);
}
TimeUnit.SECONDS.sleep(5);
service.shutdownNow();
}
}
ScheduledExecutor
を使用してTimer
と区別されるのは、Timer
がこのタスクを実行するために新しいスレッドを作成しないことであり、以前のタスクの実行時間が次のタスクとの間隔より大きくなり、次のタスクが遅延する可能性があります.
public class Main {
static final int SIZE = 10;
public static void main(String[] args) throws InterruptedException, IOException {
ExecutorService exec = Executors.newCachedThreadPool();
CountDownLatch latch = new CountDownLatch(SIZE);
int count = 10;
while (count-- > 0) {
exec.execute(() -> {
try {
TimeUnit.MILLISECONDS.sleep(100);
System.out.println("one task was finished");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
latch.countDown();
}
});
}
exec.execute(() -> {
try {
latch.await();
System.out.println("submit tasks report");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
TimeUnit.MILLISECONDS.sleep(4000);
exec.shutdownNow();
}
}
public class Main {
private static final int SIZE = 10;
private static Random random = new Random(47);
public static void main(String[] args) throws InterruptedException, IOException {
ExecutorService exec = Executors.newCachedThreadPool();
CyclicBarrier barrier = new CyclicBarrier(SIZE, () -> System.out.println("submit tasks report"));
int count = 10;
while (count-- > 0){
exec.execute(() -> {
try {
TimeUnit.MILLISECONDS.sleep(random.nextInt(1000));
System.out.println("one task was finished");
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
});
}
TimeUnit.MILLISECONDS.sleep(4000);
exec.shutdownNow();
}
}
public class Main {
private static final int SIZE = 5;
private static Random random = new Random(47);
public static void main(String[] args) throws InterruptedException, IOException {
long start = System.currentTimeMillis();
ScheduledExecutorService service = Executors.newScheduledThreadPool(SIZE);
for (int i = 0; i < SIZE; i++) {
service.schedule(() -> System.out.println(System.currentTimeMillis() - start),
random.nextInt(3000), TimeUnit.MILLISECONDS);
}
TimeUnit.SECONDS.sleep(5);
service.shutdownNow();
}
}