Философия Java3
Шрифт:
//: concurrency/Fat java
// Объекты, создание которых занимает много времени
public class Fat {
private volatile double d. // Предотвращает оптимизацию private static int counter = 0. private final int id = counter++. public FatО {
// Затратная, прервываемая операция for(int i = 1: i < 10000; i++) {
d += (Math PI + Math.E) / (double)i.
}
}
public void operationO { System out println(this); } public String toStringO { return "Fat id: " + id; } } ///:-
Мы создадим пул объектов Fat, чтобы свести к минимуму затраты на выполнение
// concurrency/SemaphoreDemo java // Тестирование класса Pool import java.util.concurrent.*; import java util *;
import static net.mindview.util.Print.*;
// Задача для получения ресурса из пула: class CheckoutTask<T> implements Runnable { private static int counter = 0; private final int id = counter++; private Pool<T> pool. public CheckoutTask(Pool<T> 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<Fat> pool =
new Pool<Fat>(Fat.class. SIZE). ExecutorService exec = Executors newCachedThreadPoolО. for(int i = 0; i < SIZE; i++)
exec.execute(new CheckoutTask<Fat>(pool)). print("All CheckoutTasks created"); List<Fat> list = new ArrayList<Fat>0. 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<T>; при вызове метода Exchanger.exchange вызов блокируется до тех пор, пока парная задача не вызовет свой метод exchange, после чего оба метода exchange завершаются, а контейнеры List<T> меняются местами:
//: concurrency/ExchangerDemo.java import java.util.concurrent.*; import java.util.*; i mport net.mi ndvi ew.uti1.*:
class ExchangerProducer<T> implements Runnable { private Generator<T> generator; private Exchanger<List<T>> exchanger; private List<T> holder; ExchangerProducer(Exchanger<Li st<T>> exchg, Generator<T> gen, List<T> holder) { exchanger = exchg; generator = gen; this.holder = holder;
}
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) {
// Приемлемый способ завершения.
}
class ExchangerConsumer<T> implements Runnable { private Exchanger<List<T>> exchanger; private List<T> holder; private volatile T value;
ExchangerConsumer(Exchanger<List<T>> ex, List<T> holder){ exchanger = ex; this.holder = holder;
}
public void runO {
} catch(InterruptedException e) {
// Приемлемый способ завершения
}
System out.printlnC'HToroBoe значение- " + value).
}
}
public class ExchangerDemo { static int size = 10; static int delay = 5; // Секунды
public static void main(String[] args) throws Exception { if(args.length > 0)
size = new lnteger(args[0]), if(args.length > 1)
delay = new Integer(args[l]); ExecutorService exec = Executors.newCachedThreadPoolО. Exchanger<List<Fat>> xc = new Exchanger<List<Fat»0; List<Fat>
producerList = new CopyOnWriteArrayList<Fat>. consumerList = new CopyOnWriteArrayList<Fat>; exec.execute(new ExchangerProducer<Fat>(xc.
BasicGenerator.create(Fat.class). producerList)); exec.execute(
new ExchangerConsumer<Fat>(xc.consumerLi st)); TimeUni t.SECONDS.sieep(delay); exec shutdownNowO;