Java se сервлеты и jsp паттерны Gof junit Log4j ant


package  by.bsu.learning; import



Pdf көрінісі
бет20/22
Дата11.12.2019
өлшемі8,99 Mb.
#53432
1   ...   14   15   16   17   18   19   20   21   22
Байланысты:
JAVA Methods Programming v2.march2015 (2)


package
 by.bsu.learning;
import
 java.util.ArrayList;
import
 java.util.List;
import
 java.util.concurrent.CountDownLatch;
import
 java.util.Random;
public
 class Student extends Thread {
 
private
 Integer idStudent;
 
private
 List taskList;
 
private
 CountDownLatch countDown;
 
public
 Student(Integer idStudent, int numberTasks) {
  this.idStudent = idStudent;
  this.countDown = new CountDownLatch(numberTasks);
  this.taskList = new ArrayList(numberTasks);
 }
 
public
 Integer getIdStudent() {
  return idStudent;
 }
 
public
 void setIdStudent(Integer idStudent) {
  this.idStudent = idStudent;
 }
 
public
 CountDownLatch getCountDownLatch() {
  return countDown;
 }

ПОТОКИ ВЫПОЛНЕНИЯ
321
 
public
 List getTaskList() {
  return taskList;
 }
 
public
 void addTask(Task task) {
   taskList.add(task);
 }
 
public
 void run() {
  int i = 0;
  for (Task inWork : taskList) {
   // на выполнение задания требуется некоторое время
   try {
    Thread.sleep(new Random().nextInt(100));
   } 
catch
 (InterruptedException e) {
    e.printStackTrace();
   } 
   // отправка ответа
 
 
 
inWork.setAnswer("Answer #" + ++i); 
   System.out.println("Answer #" + i + " from " + idStudent);
  }
  try {
   countDown.await(); // ожидание проверки заданий
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  // подсчет средней оценки за все задачи
  float averageMark = 0;
  for (Task inWork : taskList) {
   // выполнение задания
   averageMark += inWork.getMark(); // отправка ответа
  }
 
 
averageMark /= taskList.size();
  System.out.println("Student " + idStudent + ": Average mark = "
    + averageMark);
 }
}
// # 27 # поток-тьютор, проверяющий задания # Tutor.java
package
 by.bsu.learning;
import
 java.util.ArrayList;
import
 java.util.List;
import
 java.util.Random;
public
 class Tutor extends Thread {
 
private
 Integer idTutor;
 
private
 List list;
 
public
 Tutor() {
  this.list = new ArrayList<>();
 }
 
public
 Tutor(List list) {
  this.list = list;
 }

ИСПОЛЬЗОВАНИЕ КЛАССОВ И БИБЛИОТЕК
322
 
public
 Integer getIdTutor() {
  return idTutor;
 }
 
public
 void setIdTutor(Integer id) {
  this.idTutor = id;
 }
 
public
 void run() {
  for (Student st : list) {
   // проверить, выданы ли студенту задания
   List tasks = st.getTaskList();
   for (Task current : tasks) {
    // проверить наличие ответа!
    int mark = 3 + new Random().nextInt(7);
    current.setMark(mark);
    System.out.println(mark + " for student N " 
       
 
 
 
 

st.getIdStudent());
    st.getCountDownLatch().countDown();
   }
   System.out.println("All estimates made for " + st.getIdStudent());
  }
 }
}
// # 28 # класс-носитель информации # Task.java
package
 by.bsu.learning;
public
 class Task {
 
private
 String content;
 
private
 String answer;
 
private
 int mark;
 
public
 Task(String content) {
  this.content = content;
 }
 
public
 String getContent() {
  return content;
 }
 
public
 void setContent(String content) {
  this.content = content;
 }
 
public
 String getAnswer() {
  return answer;
 }
 
public
 void setAnswer(String answer) {
  this.answer = answer;
 }
 
public
 int getMark() {
  return mark;
 }
 
public
 void setMark(int mark) {
  this.mark = mark;
 }
}

ПОТОКИ ВЫПОЛНЕНИЯ
323
/* # 29 # запуск формирования группы студентов и выполнения проверки их заданий # 
RunLearning.java */
package
 by.bsu.learning;
import
 java.util.ArrayList;
public
 class RunLearning {
 
public
 static void main(String[] args) {
  final int NUMBER_TASKS_1 = 5;
 
 
Student student1 = new Student(322801, NUMBER_TASKS_1);
  for (int i = 0; i < NUMBER_TASKS_1; i++) {
   Task 


new
 Task("Task #" + i);
   student1.addTask(t);
  }
  final int NUMBER_TASKS_2 = 4;
 
 
Student student2 = new Student(322924, NUMBER_TASKS_2);
  for (int i = 0; i < NUMBER_TASKS_2; i++) {
   Task 


new
 Task("Task ##" + i);
   student2.addTask(t);
  }
 
 
ArrayList lst = new ArrayList();
  lst.add(student1);
  lst.add(student2);
 
 
Tutor tutor = new Tutor(lst);
  student1.start();
  student2.start();
  try { // поток проверки стартует с задержкой
   Thread.sleep(5000);
  } 
catch
 (InterruptedException e) {
   e.printStackTrace();
  } 
  tutor.start();
 }
}
В результате будет выведено:
Answer #1  from 322801
Answer #2  from 322801
Answer #1  from 322924
Answer #2  from 322924
Answer #3  from 322801
Answer #4  from 322801
Answer #5  from 322801
Answer #3  from 322924
Answer #4  from 322924
3 for student N%322801
6 for student N%322801
9 for student N%322801
3 for student N%322801

ИСПОЛЬЗОВАНИЕ КЛАССОВ И БИБЛИОТЕК
324
6 for student N%322801
All mark for 322801 accepted
9 for student N%322924
8 for student N%322924
3 for student N%322924
9 for student N%322924
All mark for 322924 accepted
Student 322924: Average mark = 7.25
Student 322801: Average mark = 5.4
Следует отметить, что в этом и предыдущих заданиях не полностью выполне-
ны все условия по обеспечению корректной работы приложений во всех возмож-
ных ситуациях, возникающих в условиях многопоточности. Следует рассматри-
вать  данный  пример  в  качестве  каркаса  для  построения  работоспособного 
приложения.
Обмен блокировками
Существует возможность безопасного обмена объектами, в том числе и син-
хронизированными. Функционал обмена представляет класс Exchanger с его 
единственным методом T exchange(T ob). Возвращаемый параметр метода — 
объект, который будет принят из другого потока, передаваемый параметр ob 
метода — собственный объект потока, который будет отдан другому потоку.
Поток Producer представляет информацию о количестве произведенного то-
вара, поток Consumer — о количестве проданного. В результате обмена произ-
водитель снизит план производства, если количество проданного товара меньше 
произведенного. Потребитель, к тому же, снижает цену на товар, так как посту-
пления товара больше, чем продано за время, предшествующее обмену.
/* # 30 # содержит Exchanger и представляет основу для производителя и потребителя 
# Subject.java */
package
 by.bsu.exchanger;
import
 java.util.concurrent.Exchanger;
public
 class Subject {
 
protected
 static Exchanger exchanger = new Exchanger<>();
 
private
 String name;
 
protected
 Item item;
 
public
 Subject(String name, Item item) {
  this.name = name;
  this.item = item;
 } 
 
public
 String getName() {
  return name;
 } 

ПОТОКИ ВЫПОЛНЕНИЯ
325
public
 Item getItem() {
return
 item;
}
public
 void setName(String name) {
this
.name = name;
}
public
 void setItem(Item item) {
this
.item = item;
}
}
/* # 31 # поток-производитель товара, обменивающегося информацией о планах 
производства с потребителем # Producer.java */
package
 by.bsu.exchanger;
public
 class Producer extends Subject implements Runnable {
public
 Producer(String name, Item item) {
super
(name, item);
}
public
 void run() {
try
 {
synchronized
(item) { // блок синхронизации не нужен, но показателен
int
 proposedNumber = this.getItem().getNumber(); 
// обмен синхронизированными экземплярами
item = exchanger.exchange(item); 
if
 (proposedNumber <= item.getNumber()) { 
System.out.println("Producer " + getName() 
+ " повышает план производства товара");
else
}   {
System.out.println("Producer " + getName() 
+ " снижает план производства товара");
}
}

catch
 (InterruptedException e) {
e.printStackTrace();
}
}
}
/* # 32 # поток-потребитель товара, обменивающийся уровнем продаж 
с производителем # Consumer.java */
package
 by.bsu.exchanger;
public
 class Consumer extends Subject implements Runnable {
public
 Consumer(String name, Item item) {
super
(name, item);
}
public
 void run() {
try
 {
synchronized
(item) { // блок синхронизации не нужен, но показателен

ИСПОЛЬЗОВАНИЕ КЛАССОВ И БИБЛИОТЕК
326
int
 requiredNumber = item.getNumber();
item 

exchanger.exchange(item); // обмен
if
 (requiredNumber >= item.getNumber()) {
System.out.println("Consumer " + getName() 
+ " повышает стоимость товара");
else
}   {
System.out.println("Consumer " + getName() 
+ " снижает стоимость товара");
}
}
catch
}   (InterruptedException e) {
e.printStackTrace();
}
}
}
/* # 33 # класс-описание товара # Item.java */
package
 by.bsu.exchanger;
public
 class Item {
private
 Integer id;
private
 Integer number;
public
 Item(Integer id, Integer number) {
super
();
this
.id = id;
this
.number = number;
}
public
 Integer getId() {
return
 id;
}
public
 Integer getNumber() {
return
 number;
}
}
/* # 34 # процесс обмена # RunExchange.java */
package
 by.bsu.exchanger;
public
 class RunExchange {
public
 static void main(String[ ] args) {
Item ss1 = new Item(34, 2200);
Item ss2 = new Item(34, 2100);
new
 Thread(new Producer("HP ", ss1)).start();
new
 Thread(new Consumer("RETAIL Trade", ss2)).start();
}
}
В результате будет получено:
Consumer RETAIL Trade снижает стоимость товара
Producer HP снижает план производства товара

ПОТОКИ ВЫПОЛНЕНИЯ
327
Альтернатива synchronized
Синхронизация  ресурса  ключевым  словом  synchronized  накладывает  до-
статочно  жесткие  правила  на  освобождение  этого  ресурса.  Интерфейс  Lock 
представляет собой некоторое обобщение синхронизации. Появляется возмож-
ность провести опрос о блокировании, установить время ожидания блокиров-
ки  и  условия  ее  прерывания.  Интерфейс  также  оптимизирует  работу  JVM 
с процессами конкурирования за освобождаемые ресурсы.
Класс ReentrantLock представляет два основных метода:
void lock() — получает блокировку экземпляра. Если экземпляр блокирован 
другим потоком, то поток отключается и бездействует до освобождения экзем-
пляра;
void unlock() — освобождает блокировку экземпляра. Если текущий по-
ток  не  является  обладателем  блокировки,  генерируется  исключение 
IllegalMonitorStateException.
Шаблонное применение этих методов после объявления экземпляра locking 
класса ReentrantLock:
locking.lock();
try
 {
   // some code here 
finally {
locking.unlock();
}
Данная  конструкция  копирует  функциональность  блока  synchronized
Гибкость классу предоставляют методы:
boolean  tryLock()  —  получает  блокировку  экземпляра.  Если  блокировка 
выполнена другим потоком, то метод сразу возвращает false;
boolean tryLock(long timeout, TimeUnit unit) — получает блокировку эк-
земпляра. Если экземпляр блокирован другим потоком, то метод приостанав-
ливает поток на время timeout, и если блокировка становится возможна в тече-
ние  этого  интервала,  то  поток  ее  получает,  если  же  блокировка  недоступна, 
то метод возвращает false.
Метод lock() и оба метода tryLock() при повторном успешном получении 
блокировки в одном и том же потоке увеличивают счетчик блокировок на еди-
ницу, что требует соответствующего числа снятий блокировки.
Класс Condition предназначен для управления блокировкой. Ссылку на эк-
земпляр можно получить только из объекта типа Lock методом newCondition()
Расширение возможностей происходит за счет методов await() и signal(), функ-
циональность которых подобна действию методов wait() и notify() класса Object.
Пусть необходим нереляционный способ сохранения информации в коллек-
ции, когда неделимым квантом информации считается пара или более следую-
щих друг за другом элементов. То есть добавление и удаление элементов может 

ИСПОЛЬЗОВАНИЕ КЛАССОВ И БИБЛИОТЕК
328
осуществляться только парами и другой поток не может добавить/удалить свои 
элементы,  пока  заблокировавший  коллекцию  поток  полностью  не  выполнит 
свои действия.
/* # 35 # ресурсы добавляются и удаляются только парами # DoubleResource.java */
package
 by.bsu.lock;
import
 java.util.Deque;
import
 java.util.LinkedList;
import
 java.util.Random;
import
 java.util.concurrent.TimeUnit;
import
 java.util.concurrent.locks.Condition;
import
 java.util.concurrent.locks.Lock;
import
 java.util.concurrent.locks.ReentrantLock;
public
 class DoubleResource {
 
private
 Deque list = new LinkedList();
 
private
 Lock lock = new ReentrantLock();
 
private
 Condition isFree = lock.newCondition();
 
public
 void adding(String str, int i) {
  try {
   lock.lock();
 
 
 
list.add(i + "<" + str);
   TimeUnit.MILLISECONDS.sleep(new Random().nextInt(50));
 
 
 
list.add(str + ">" + i);
   isFree.signal();
  } 
catch
 (InterruptedException e) {
   e.printStackTrace();
  } 
finally
 {
   lock.unlock();
  }
 }
 
public
 String deleting() {
  lock.lock();
 
 
String s = list.poll();
 
 
s += list.poll();
  isFree.signal();
  lock.unlock();
  return s;
 }
 
public
 String toString() {
  return list.toString();
 }
}
/* # 36 # поток доступа к ресурсу # ResThread.java */
package
 by.bsu.lock;
import
 java.util.Random;
public
 class ResThread extends Thread {
 
private
 DoubleResource resource;
 
public
 ResThread(String name, DoubleResource rs) {

ПОТОКИ ВЫПОЛНЕНИЯ
329
  super(name);
 
 
resource = rs;
 }
 
public
 void run() {
  for (int i = 1; i < 4; i++) {
   if (new Random().nextInt(2) > 0) {
    resource.adding(getName(), 
i);
   } 
else
 {
    resource.deleting();
   }
  }
 }
}
/* # 37 # запуск процессов доступа к ресурсу # SynchroMain.java */
package
 by.bsu.lock;
import
 java.util.concurrent.TimeUnit;
public
 class SynchroMain {
 
public
 static void main(String[ ] args) throws InterruptedException {
  for (int i = 0; i < 5; i++) {
   DoubleResource 
resource 

new
 DoubleResource();
   new ResThread("a", resource).start();
   new ResThread("Z", resource).start();
   new ResThread("#", resource).start();
   TimeUnit.MILLISECONDS.sleep(1_000);
   System.out.println(resource);
  }
 }
}
В результате может быть получено:
[11, 22, 11, 1<#, #>1, 33, 3<#, #>3]
[]
[22, 33, 11, 33, 2<#, #>2]
[33, 33, 3<#, #>3]
[11, 22, 33, 3<#, #>3]
где результат с пустыми скобками свидетельствует, что попыток изъятия пар было 
больше, чем попыток добавления. Нерезультативные попытки не фиксировались.
ExecutorService и Callable
В альтернативной системе управления потоками разработан механизм ис-
полнителей, функции которого заключаются в запуске отдельных потоков и их 
групп, а также в управлении ими: принудительной остановке, контроле числа 
работающих потоков и планирования их запуска.

ИСПОЛЬЗОВАНИЕ КЛАССОВ И БИБЛИОТЕК
330
Класс ExecutorService методом execute(Runnable thread) запускает тради-
ционные потоки, метод же submit(Callable task) запускает потоки с воз-
вращаемым значением. Метод shutdown() останавливает все запущенные им 
ранее потоки и прекращает действие самого исполнителя. Статические методы 
newSingleThreadExecutor()  и  newFixedThreadPool(int  numThreads)  класса 
Executors определяют правила, по которым работает ExecutorService, а имен-
но  первый  позволяет  исполнителю  запускать  только  один  поток,  второй  — 
не более чем указано в параметре numThreads, ставя другие потоки в очередь 
ожидания окончания уже запущенных потоков.
/* # 38 # поток с возвращением результата # CalcCallable.java */
package
 by.bsu.future;
import
 java.util.Random;
import
 java.util.concurrent.Callable;
public
 class CalcCallable implements Callable {
 @Override
 
public
 Number call() throws Exception {
 
 
Number res = new Random().nextGaussian(); // имитация вычислений
           
return
 res;
 }
}
/* # 39 # запуск потока и извлечение результата его выполнения # CalcRunner.java */
package
 by.bsu.future;
import
 java.util.concurrent.ExecutionException;
import
 java.util.concurrent.ExecutorService;
import
 java.util.concurrent.Executors;
import
 java.util.concurrent.Future;
public
 class CalcRunner {
 
public
 static void main(String[] args) {
 
 
ExecutorService es = Executors.newSingleThreadExecutor();
 
 
Future future = es.submit(new CalcCallable()); 
  es.shutdown();
  try {
   System.out.println(future.get());
  } 
catch
 (InterruptedException | ExecutionException e) {
   e.printStackTrace();
  }
 }
}
Интерфейс Callable представляет поток, возвращающий значение вызываю-
щему потоку. Определяет один метод V call() throws Exception, в код реализации 
которого и следует поместить решаемую задачу. Результат выполнения метода 
call() может быть получен через экземпляр класса Future, методами V get() или 
V
 get(long timeout, TimeUnit unit), как и продемонстрировано в предыдущем 

ПОТОКИ ВЫПОЛНЕНИЯ
331
примере. Перед извлечением результатов работы потока Callable можно прове-
рить, завершилась ли задача успешно, методами isDone() и isCancelled() соот-
ветственно.
/* # 40 # список обрабатываемых объектов # ProductList.java */
package
 by.bsu.future;
import
 java.util.ArrayDeque;
public
 class ProductList {
 
private
 static ArrayDeque arr = new ArrayDeque() {
  {
   this.add("Product 1");
   this.add("Product 2");
   this.add("Product 3");
   this.add("Product 4");
   this.add("Product 5");
  }
 };
 
public
 static String getProduct() {
  return arr.poll();
 }
}
/* # 41 # поток обработки экземпляра продукта # BaseCallable.java */
package
 by.bsu.future;
import
 java.util.concurrent.Callable;
import
 java.util.concurrent.TimeUnit;
public
 class BaseCallable implements Callable {
 @Override
 
public
 String call() throws Exception {
 
 
String product = ProductList.getProduct();
 
 
String result = null;
  if (product != null) {
 
 
 
result = product + " done";
  } 
else
 {
 
 
 
result = "productList is empty";
  }
  TimeUnit.MILLISECONDS.sleep(100);
  System.out.println(result);
  return result;
 }
}
/* # 42 # запуск пула потоков и извлечение результатов их работы # RunExecutor.java */
package
 by.bsu.future;
import
 java.util.ArrayList;
import
 java.util.concurrent.ExecutorService;
import
 java.util.concurrent.Executors;

ИСПОЛЬЗОВАНИЕ КЛАССОВ И БИБЛИОТЕК
332
import
 java.util.concurrent.Future;
public
 class RunExecutor {
 
public
 static void main(String[] args) throws Exception {
 
 
ArrayList> list = new ArrayList>();
 
 
ExecutorService es = Executors.newFixedThreadPool(3);
  for (int i = 0; i < 7; i++) {
   list.add(es.submit(new BaseCallable()));
  }
  es.shutdown();
  for (Future future : list) {
   System.out.println(future.get() + " result fixed");
  }
 }
}
В результате выполнения будет, возможно, выведено:
Product 3 done
Product 1 done
Product 2 done
Product 1 done result fixed
Product 3 done result fixed
Product 2 done result fixed
productList is empty
Product 5 done
Product 4 done
Product 4 done result fixed
Product 5 done result fixed
productList is empty result fixed
productList is empty
productList is empty result fixed
Phaser
Более сложное поведение этого синхронизатора Phaser напоминает поведе-
ние  CyclicBarrier,  однако  число  участников  синхронизации  может  меняться. 
Участвующие стороны сначала должны зарегистрироваться phaser-объектом. Ре-
гистрация  осуществляется  с  помощью  методов  register(),  bulkRegister(int  parties) 
или подходящего конструктора. Выход из синхронизации phaser-объектом про-
изводит  метод  arriveAndDeregister(),  причем  выход  из  числа  синхронизируе-
мых сторон может быть и в случае, когда поток завершил выполнение, и в слу-
чае, когда поток все еще выполняется. Основным  назначением класса Phaser 
является синхронизация потоков, выполнение которых требуется разбить на от-
дельные этапы (фазы), а эти фазы, в свою очередь, необходимо синхронизо-
вать. Phaser может как задержать поток, пока другие потоки не достигнут конца 

ПОТОКИ ВЫПОЛНЕНИЯ
333
текущей фазы методом arriveAndAwaitAdvance(), так и пропустить поток, от-
метив лишь окончание какой-либо фазы методом arrive().
/* # 43 # поток # Truck.java */
package
 by.bsu.phaser;
import
 java.util.ArrayDeque;
import
 java.util.Queue;
import
 java.util.Random;
import
 java.util.concurrent.Phaser;
public
 class Truck implements Runnable {
 
private
 Phaser phaser;
 
private
 String number;
 
private
 int capacity;
 
private
 Storage storafeFrom;
 
private
 Storage storageTo;
 
private
 Queue bodyStorage;
 
public
 Truck(Phaser phaser, String name, int capacity, Storage stFrom,
   Storage 
stTo) 
{
  this.phaser = phaser;
  this.number = name;
  this.capacity = capacity;
  this.bodyStorage = new ArrayDeque(capacity);
  this.storafeFrom = stFrom;
  this.storageTo = stTo;
  this.phaser.register();
 }
 
public
 void run() {
  loadTruck();
  phaser.arriveAndAwaitAdvance();
  goTruck();
  phaser.arriveAndAwaitAdvance();
  unloadTruck();
  phaser.arriveAndDeregister();
 }
 
private
 void loadTruck() {
  for (int i = 0; i < capacity; i++) {
   Item g = storafeFrom.getGood();
   if (g == null) { // если в хранилище больше нет товара, 
 
 
 
 
       // загрузка грузовика прерывается
    return;
   }
   bodyStorage.add(g);
   System.out.println("Грузовик " + number + " загрузил товар №"
     + g.getRegistrationNumber());
   try {
    Thread.sleep(50);
   } 
catch
 (InterruptedException e) {
    e.printStackTrace();

ИСПОЛЬЗОВАНИЕ КЛАССОВ И БИБЛИОТЕК
334
   }
  }
 }
 
private
 void unloadTruck() {
  int size = bodyStorage.size();
  for (int i = 0; i < size; i++) {
 
 
 
Item g = bodyStorage.poll();
   storageTo.setGood(g);
   System.out.println("Грузовик " + number + " разгрузил товар №"
     + 
g.getRegistrationNumber());
   try {
    Thread.sleep(50);
   } 
catch
 (InterruptedException e) {
    e.printStackTrace();
   }
  }
 }
 
private
 void goTruck() {
  try {
   Thread.sleep(new Random(100).nextInt(500));
   System.out.println("Грузовик " + number + " начал поездку.");
   Thread.sleep(new Random(100).nextInt(1000));
   System.out.println("Грузовик " + number + " завершил поездку.");
  } 
catch
 (InterruptedException e) {
   e.printStackTrace();
  }
 }
}
/* # 44 # перевозимый товар # Item.java */
package
 by.bsu.phaser;
public
 class Item {
 
private
 int registrationNumber;
 
public
 Item(int number) {
  this.registrationNumber = number;
 }
 
public
 int getRegistrationNumber() {
  return registrationNumber;
 }
}
/* # 45 # склад-коллекция # Storage.java */
package
 by.bsu.phaser;
import
 java.util.Iterator;
import
 java.util.List;
import
 java.util.Queue;
import
 java.util.concurrent.LinkedBlockingQueue;
public
 class Storage implements Iterable {

ПОТОКИ ВЫПОЛНЕНИЯ
335
 
public
 static final int DEFAULT_STORAGE_CAPACITY = 20;
 
private
 Queue goods = null;
 
private
 Storage() {
  goods 

  new
 LinkedBlockingQueue(DEFAULT_STORAGE_CAPACITY);
 }
 
private
 Storage(int capacity) {
  goods 

new
 LinkedBlockingQueue(capacity);
 }
 
public
 static Storage createStorage(int capacity) {
 
 
Storage storage = new Storage(capacity);
  return storage;
 }
 
public
 static Storage createStorage(int capacity, List goods) {
 
 
Storage storage = new Storage(capacity);
  storage.goods.addAll(goods);
  return storage;
 }
 
public
 Item getGood() {
  return goods.poll();
 }
 
public
 boolean setGood(Item good) {
  return goods.add(good);
 }
 @Override
 
public
 Iterator iterator() {
  return goods.iterator();
 }
}
/* # 46 # запуск процесса # PhaserDemo.java */
package
 by.bsu.phaser;
import
 java.util.Arrays;
import
 java.util.Iterator;
import
 java.util.List;
import
 java.util.concurrent.Phaser;
public
 class PhaserDemo {
 
public
 static void main(String[] args) {
  // создание коллекцию товаров
  Item[] goods = new Item[20];
  for (int i = 0; i < goods.length; i++) {
   goods[i] 

new
 Item(i + 1);
  }
 
 
List listGood = Arrays.asList(goods);
  // создание склада, из которого забирают товары
  Storage storageA = Storage.createStorage(listGood.size(), listGood);
  // создание склада, куда перевозят товары
 
 
Storage storageB = Storage.createStorage(listGood.size());
  // создание фазера для синхронизации движения колонны грузовиков

ИСПОЛЬЗОВАНИЕ КЛАССОВ И БИБЛИОТЕК
336
  Phaser phaser = new Phaser();
  phaser.register();
  int currentPhase;
  // создание колонны грузовиков
  Thread tr1 = new Thread(new Truck(phaser, "tr1", 5, storageA, storageB));
 
 
Thread tr2 = new Thread(new Truck(phaser, "tr2", 6, storageA, storageB));
 
 
Thread tr3 = new Thread(new Truck(phaser, "tr3", 7, storageA, storageB));
 
 
printGoodsToConsole("Товары на складе A", storageA);
 
 
printGoodsToConsole("Товары на складе B", storageB);
  // запуск колонны грузовиков на загрузку на одном складе + поездку +
  // разгрузку на другом складе
  tr1.start();
  tr2.start();
  tr3.start();
  // синхронизация загрузки
  currentPhase = phaser.getPhase();
  phaser.arriveAndAwaitAdvance();
  System.out.println("Загрузка колонны завершена. Фаза " + currentPhase
 
 
 
 
+ " завершена.");
  // синхронизация поездки
  currentPhase = phaser.getPhase();
  phaser.arriveAndAwaitAdvance();
  System.out.println("Поездка колонны завершена. Фаза " + currentPhase
 
 
 
 
+ " завершена.");
  // синхронизация разгрузки
  currentPhase = phaser.getPhase();
  phaser.arriveAndAwaitAdvance();
  System.out.println("Разгрузка колонны завершена. Фаза " + currentPhase
 
 
 
 
+ " завершена.");
  phaser.arriveAndDeregister();
  if (phaser.isTerminated()) {
 
 
 
System.out.println("Фазы синхронизированы и завершены.");
  }
 
 
printGoodsToConsole("Товары на складе A", storageA);
 
 
printGoodsToConsole("Товары на складе B", storageB);
 }
 
public
 static void printGoodsToConsole(String title, Storage storage) {
  System.out.println(title);
 
 
Iterator goodIterator = storage.iterator();
  while (goodIterator.hasNext()) {
 
 
 
System.out.print(goodIterator.next().getRegistrationNumber() + " ");
  }
  System.out.println();
 }
}
Товары на складе A
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 
Товары на складе B
Грузовик tr1 загрузил товар №1

ПОТОКИ ВЫПОЛНЕНИЯ
337
Грузовик tr2 загрузил товар №2
Грузовик tr3 загрузил товар №3
Грузовик tr2 загрузил товар №4
Грузовик tr1 загрузил товар №5
Грузовик tr3 загрузил товар №6
Грузовик tr2 загрузил товар №7
Грузовик tr1 загрузил товар №8
Грузовик tr3 загрузил товар №9
Грузовик tr2 загрузил товар №10
Грузовик tr3 загрузил товар №11
Грузовик tr1 загрузил товар №12
Грузовик tr2 загрузил товар №13
Грузовик tr3 загрузил товар №14
Грузовик tr1 загрузил товар №15
Грузовик tr2 загрузил товар №16
Грузовик tr3 загрузил товар №17
Грузовик tr3 загрузил товар №18
Загрузка колонны завершена. Фаза 0 завершена.
Грузовик tr2 начал поездку.
Грузовик tr1 начал поездку.
Грузовик tr3 начал поездку.
Грузовик tr1 завершил поездку.
Грузовик tr3 завершил поездку.
Грузовик tr2 завершил поездку.
Грузовик tr2 разгрузил товар №2
Грузовик tr1 разгрузил товар №1
Грузовик tr3 разгрузил товар №3
Поездка колонны завершена. Фаза 1 завершена.
Грузовик tr2 разгрузил товар №4
Грузовик tr1 разгрузил товар №5
Грузовик tr3 разгрузил товар №6
Грузовик tr2 разгрузил товар №7
Грузовик tr1 разгрузил товар №8
Грузовик tr3 разгрузил товар №9
Грузовик tr2 разгрузил товар №10
Грузовик tr1 разгрузил товар №12
Грузовик tr3 разгрузил товар №11
Грузовик tr2 разгрузил товар №13
Грузовик tr1 разгрузил товар №15
Грузовик tr3 разгрузил товар №14
Грузовик tr2 разгрузил товар №16
Грузовик tr3 разгрузил товар №17

ИСПОЛЬЗОВАНИЕ КЛАССОВ И БИБЛИОТЕК
338
Грузовик tr3 разгрузил товар №18
Разгрузка колонны завершена. Фаза 2 завершена.
Фазы синхронизированы и завершены.
Товары на складе A
19 20 
Товары на складе B
2 3 1 4 5 6 7 8 9 10 12 11 13 15 14 16 17 18 
Задания к главе 11
Вариант А
Разработать многопоточное приложение.
Использовать возможности, предоставляемые пакетом java.util.concurrent.
Не использовать слово synchronized.
Все сущности, желающие получить доступ к ресурсу, должны быть потоками.
Использовать возможности ООП.
Не  использовать  графический  интерфейс.  Приложение  должно  быть  кон-
сольным.
1.  Порт. Корабли заходят в порт для разгрузки/загрузки контейнеров. Число 
контейнеров, находящихся в текущий момент в порту и на корабле, должно 
быть неотрицательным и превышающим заданную грузоподъемность суд-
на и вместимость порта. В порту работает несколько причалов. У одного 
причала может стоять один корабль. Корабль может загружаться у причала, 
разгружаться или выполнять оба действия.
2.  Маленькая библиотека. Доступны для чтения несколько книг. Одинаковых 
книг  в  библиотеке  нет.  Некоторые  выдаются  на  руки,  некоторые  только 
в читальный зал. Читатель может брать на руки и в читальный зал не-
сколько книг.
3.  Автостоянка. Доступно несколько машиномест. На одном месте может 
находиться только один автомобиль. Если все места заняты, то автомо-
биль не станет ждать больше определенного времени и уедет на другую 
стоянку.
4.  CallCenter. В организации работает несколько операторов. Оператор может 
обслуживать только одного клиента, остальные должны ждать своей очереди. 
Клиент может положить трубку и перезвонить еще раз через некоторое время.
5.  Автобусные  остановки.  На  маршруте  несколько  остановок.  На  одной 
остановке  может  останавливаться  несколько  автобусов  одновременно, 
но не более заданного числа.
6.  Свободная  касса.  В  ресторане  быстрого  обслуживания  есть  несколько 
касс. Посетители стоят в очереди в конкретную кассу, но могут перейти 
в другую очередь при уменьшении или исчезновении там очереди.

ПОТОКИ ВЫПОЛНЕНИЯ
339
7.  Тоннель. В горах существует два железнодорожных тоннеля, по которым 
поезда могут двигаться в обоих направлениях. По обоим концам тоннеля 
собралось много поездов. Обеспечить безопасное прохождение тоннелей 
в  обоих  направлениях.  Поезд  можно  перенаправить  из  одного  тоннеля 
в другой при превышении заданного времени ожидания на проезд.
8.  Банк. Имеется банк с кассирами, клиентами и их счетами. Клиент может 
снимать/пополнять/переводить/оплачивать/обменивать  денежные  средст-
ва.  Кассир  последовательно  обслуживает  клиентов.  Поток-наблюдатель 
следит, чтобы в кассах всегда были наличные, при скоплении денег более 
определенной суммы, часть их переводится в хранилище, при истощении 
запасов наличных происходит пополнение из хранилища.
9.  Аукцион. На торги выставляется несколько лотов. Участники аукциона де-
лают заявки. Заявку можно корректировать в сторону увеличения несколь-
ко раз за торги одного лота. Аукцион определяет победителя и переходит 
к следующему лоту. Участник, не заплативший за лот в заданный промежу-
ток времени, отстраняется на несколько лотов от торгов.
10. Биржа. На торгах брокеры предлагают акции нескольких фирм. На бирже 
совершаются действия по купле-продаже акций. В зависимости от количе-
ства проданных-купленных акций их цена изменяется. Брокеры предлага-
ют к продаже некоторую часть акций. От активности и роста-падения коти-
ровок акций изменяется индекс биржи. Биржа может приостановить торги 
при резком падении индекса.
11.  Аэропорт. Посадка/высадка пассажиров может осуществляться через конечное 
число терминалов и наземным способом через конечное число трапов. Самолеты 
бывают разной вместимости и дальности полета. Организовать функционирова-
ние аэропорта, если пунктов назначения 4–6, и зон дальности 2–3.
Вариант B
Для заданий варианта В гл. 4 организовать синхронизированный доступ к ре-
сурсам (файлам). Для каждого процесса создать отдельный поток выполнения.
Тестовые задания к главе 11
Вопрос 11.1.
Дан класс:
class InThread implements Runnable{
 
public void run() {
 
 
System.out.println("running..."); 
 
}
}

ИСПОЛЬЗОВАНИЕ КЛАССОВ И БИБЛИОТЕК
340
Укажите правильные варианты создания потокового объекта (1):
1)  new Thread().new InThread();
2)  new Runnable(new InThread());
3)  new Thread(Intread); 
4)  new Thread(new InThread());
5)  new InThread().
Вопрос 11.2.
Укажите методы, определенные в классе java.lang.Thread (4):
1)  join()
2)  getPrioroty()
3)  wait()
4)  notifyAll()
5)  sleep()
6)  getName()
Вопрос 11.3.
Укажите состояния потока, при вызове на которых метод isAlive() класса 
java.lang.Thread вернет значение true (4):
1)  NEW
2)  RUNNABLE
3)  BLOCKED
4)  WAITING
5)  TIMED_WAITING
6)  TERMINATED
Вопрос 11.4.
Дан код:
class InThread implements Runnable{
 
public void run() {System.out.println("running..."); 
}
}
public class Quest {
public static void main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(2);
exec.execute(new InThread());  exec.execute(new InThread());
exec.execute(new InThread());  exec.execute(new InThread());
exec.execute(new InThread());  exec.execute(new InThread());
exec.shutdown(); while (!exec.isTerminated()) {   }
}}

ПОТОКИ ВЫПОЛНЕНИЯ
Сколько потоков выполнит объект exec при запуске этого кода (1)? 
1)  2
2)  4
3)  0
4)  6
5)  столько, сколько успеет до завершения метода main()
Вопрос 11.5.
Дан класс Lamp(лампочка). Расставьте указанные ниже строки кода метода 
turnOn() так, чтобы не допустить ситуации включения лампочки, когда она уже 
включена (поле lamp имеет значение true, когда лампочка включена):
class Lamp {
 
private boolean lamp = false;
 
public synchronized void turnOn() throws InterruptedException {
 
 
________________ 
}}
 
 
a)  lamp = true;
 
 
b)  notify();
 
 
c)  while (lamp == true) wait();
Выберите один вариант (1): 
1)  abc;
2)  bca;
3)  acb;
4)  cba; 
5)  cab.

342


Достарыңызбен бөлісу:
1   ...   14   15   16   17   18   19   20   21   22




©engime.org 2024
әкімшілігінің қараңыз

    Басты бет