Спочатку декілька вступних слів. В наш час, коли однопроцесорні ПК починають переходити в розряд музейних експонатів на сцені з"явилися "Ріал монстерс" потипу: "Гикач", "Обліна", "Нечупара", "Гримль" (2-х, 4-х, 6-и, 8-и) ядерні. Розробники Java давно вже граються з багатопоточністю. Якщо Ви хоч трохи її бачили, то точно знаєте про інтерфейс Runnable та клас Threads. Проте, на місці ніхто не стоїть, і в Java SE5, з'явилася супер-пупер-мега бібліотека з назвою java.util.concurrent.*;
Значить, товариш Еккель каже: "CountDownLatch - клас синхронізує задачі і заставляє їх очікувати завершення групи операцій, що виконуються іншими задачами".
Об"єкту CountDownLatch надається початкове значення лічильника, а всі задачі, які викликають await(), доречі забігаючи на перед, нам цікаві два методи, цього "щастя": вище згаданий await() та нище описаний countDown(); Так от, якщо в методі є await() цього каунта, то він собі чекає, як вірний песик, поки інші методи не откаунтаудять до нуля і він зможе кинутись в бій, аби вибивати для себе місце під сонцем, тобто пару тактових ударів серця комп"ютера. Необхідно обов"язково сказати, що даний клас є одноразовий, і може каунтданиться тільки в низ до нуля, тобто ні кроку назад, як шльопки. Якщо Вам треба щось, що може вальсувати вверх-вниз, то Вам до CyclicBarrier, але це зовсім інша історія...Дуже важливо: задачі, які викликають в собі countDown(), не блокуються на час виклика. + один процес може не один раз каунтдаунить.
Приклад, відповідно, теж брався з усіма любимого і читаного.
Значить ідея, така:
Створюється "тьма" потоків, вони виконуються і кожент каунтить по разу до поки не стане нуль, після чого бідолаха, який сидів і чекав з await() - ом виривається і виконується. До речі, хто не чув про ExecutorService, то треба знайти і прочитати, це теж щастя. яке привалило з Java SE5.
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
class TaskPoriton implements Runnable{
private static int counter = 0;
private final int id = counter ++;
private static Random rand = new Random(47);
private final CountDownLatch latch;
public TaskPoriton(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
doWork();
latch.countDown();
}
void doWork(){
try {
TimeUnit.SECONDS.sleep(rand.nextInt(20));
System.out.println(this + " ended!!!");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class WaitingTask implements Runnable{
private static int counter = 0;
private final int id = counter ++;
private static Random rand = new Random(47);
private final CountDownLatch latch;
public WaitingTask(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
//Як сказали б в "Простоквашино" - : "Вот это коварный тип", який чекає нуля.
try {
latch.await();
TimeUnit.SECONDS.sleep(rand.nextInt(20));
System.out.println("============="+this + "cross barier");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class CountDownLatchUse {
static final int SIZE = 100;
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
CountDownLatch latch = new CountDownLatch(SIZE);
//Для наочності поміняно, спочатку створюються "паспжири", які чекають на маршрутку
for (int i = 0; i < 10; i++)
exec.execute(new WaitingTask(latch));А тут скажемо так, їдуть ті кого спочатку треба висадить, щоб могли зайти інші....
for (int i = 0; i < SIZE; i++)
exec.execute(new TaskPoriton(latch));
System.out.println("All processes started -- >");
exec.shutdown();
}
}
Немає коментарів:
Дописати коментар