public void operationO { System out println(this); } public String toStringO { return "Fat id: " + id; } } ///:-
Мы создадим пул объектов Fat, чтобы свести к минимуму затраты на выполнение конструктора. Для тестирования класса Pool будет создана задача, которая забирает объекты Fat для использования, удерживает их в течение некоторого времени, а затем возвращает обратно:
// concurrency/SemaphoreDemo java // Тестирование класса Pool import java.util.concurrent.*; import java util *;
import static net.mindview.util.Print.*;
// Задача для получения ресурса из пула: class CheckoutTask
}
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
new Pool
exec.execute(new CheckoutTask
}
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,
Exchanger
Класс Exchanger представляет собой «барьер», который меняет местами объекты двух задач. На подходе к барьеру задачи имеют один объект, а на выходе — объект, ранее удерживавшийся другой задачей. Объекты Exchanger обычно используются в тех ситуациях, когда одна задача создает высокозатратные объекты, а другая задача эти объекты потребляет.
Чтобы опробовать на практике класс Exchanger, мы создадим задачу-постав-щика и задачу-потребителя, которые благодаря параметризации и генераторам могут работать с объектами любого типа. Затем эти параметризованные задачи будут применены к классу Fat. ExchangerProducer и ExchangerConsumer меняют местами List
//: concurrency/ExchangerDemo.java import java.util.concurrent.*; import java.util.*; i mport net.mi ndvi ew.uti1.*:
class ExchangerProducer> exchanger; private List
}
public void run() { try {
while(IThread.interruptedO) {
for(int i =0; i < ExchangerDemo size; i++)
hoi der.add(generator. nextO); // Заполненный контейнер заменяется пустым: holder = exchanger exchange(holder);
}
} catchdnterruptedException e) {
// Приемлемый способ завершения.
}