×
Traktatov.net » Философия Java » Читать онлайн
Страница 382 из 395 Настройки

Мы создадим пул объектов Fat, чтобы свести к минимуму затраты на выполнение конструктора. Для тестирования класса Pool будет создана задача, которая забирает объекты Fat для использования, удерживает их в течение некоторого времени, а затем возвращает обратно:

// concurrency/SemaphoreDemo java // Тестирование класса Pool import java.util.concurrent.*; import java util *;

import static net.mindview.util.Print.*;

// Задача для получения ресурса из пула: class CheckoutTask implements Runnable { private static int counter = 0; private final int id = counter++; private Pool pool. public CheckoutTask(Pool pool) { this.pool = pool;

}

public void run() { try {

T item = pool.checkoutО;

print(this + "checked out " + item); продолжение &

TimeUnit SECONDS sleep(l), pri nt(thi s +"checking in " + item), pool checkln(item). } catch(InterruptedException e) {

// Приемлемый способ завершения

}

}

public String toStringO {

return "CheckoutTask " + id + " ";

public class SemaphoreDemo {

final static int SIZE = 25;

public static void main(String[] args) throws Exception { final Pool pool =

new Pool(Fat.class. SIZE). ExecutorService exec = Executors newCachedThreadPoolО. for(int i = 0; i < SIZE; i++)

exec.execute(new CheckoutTask(pool)). print("All CheckoutTasks created"); List list = new ArrayList0. for(int i = 0; i < SIZE; i++) { Fat f = pool.checkout О. printnb(i + " mainO thread checked out "). f operationO; list add(f);

}

Future blocked = exec submit(new RunnableO { public void runO { try {

// Семафор предотвращает лишний вызов checkout. // поэтому следующий вызов блокируется: pool checkOutO. } catch(InterruptedException e) {

pri nt("checkout() Interrupted");

}

}

}):

TimeUnit.SECONDS sleep(2);

blocked.cancel(true); // Выход из заблокированного вызова print("Checking in objects in " + list); for(Fat f • list)

pool checkln(f); for(Fat f : list)

pool.checkln(f); // Второй вызов checkln игнорируется exec.shutdown О;

}

} ///:-

В коде main() создается объект Pool для хранения объектов Fat, после чего группа задач CheckoutTask начинает использовать Pool. Далее поток main() начинает выдавать объекты Fat, не возвращая их обратно. После того как все объекты пула будут выданы, семафор запрещает дальнейшие выдачи. Метод run() блокируется, и через две секунды вызывается метод cancel(). Лишние возвраты Pool игнорирует.

Exchanger

Класс Exchanger представляет собой «барьер», который меняет местами объекты двух задач. На подходе к барьеру задачи имеют один объект, а на выходе — объект, ранее удерживавшийся другой задачей. Объекты Exchanger обычно используются в тех ситуациях, когда одна задача создает высокозатратные объекты, а другая задача эти объекты потребляет.

Чтобы опробовать на практике класс Exchanger, мы создадим задачу-постав-щика и задачу-потребителя, которые благодаря параметризации и генераторам могут работать с объектами любого типа. Затем эти параметризованные задачи будут применены к классу Fat. ExchangerProducer и ExchangerConsumer меняют местами List; при вызове метода Exchanger.exchange() вызов блокируется до тех пор, пока парная задача не вызовет свой метод exchange(), после чего оба метода exchange() завершаются, а контейнеры List меняются местами: