
Розробники 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(); } }
Немає коментарів:
Дописати коментар