Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

java / labs2 / lab1

.doc
Скачиваний:
85
Добавлен:
17.04.2018
Размер:
33.28 Кб
Скачать

Лабораторная работа №1.

Расширенные возможности создания многопоточных приложений

Цель работы: 1) научиться использовать расширенные возможности создания многопоточных приложений на Java.

Продолжительность работы: 4 часа.

    1. Теоретические сведения

Теоретические сведения и подробное описание очередей и исполнителей можно найти в лекциях и по .адресу: http://java.sun.com/docs/books/tutorial/essential/concurrency/highlevel.html

      1. Пример использования очередей

В нижеприведенном примере симулируется ситуация, когда в какое-то хранилище загружается что-то, и одновременно разгружается. В программе представлено два потока (плюс один поток программы). Один поток загружает в хранилище объекты, а второй их оттуда разгружает.

Хранилище имеет ограниченный рамер (константа STORAGE_SIZE). Если места в хранилище нет, погрузчик ожидает освобождения места. С другой стороны, разгрузчик ожидает наличие чего разгружать, если на складе пусто. При окончании загрузки (флаг loadFinished) разгрузчик довыгружает остатки и завершает работу, при этом вместо метода take используется метод poll, т.к.poll в случае если хранилище пусто, не ожидает появления в нем чего-либо, а возвращает null.

Если использовать только take(), то по окончанию загрузки поток-разгрузчик заблокируется навсегда. А если использовать только poll(), то в случае если разгрузка происходит быстрее, чем погрузка, то поток преждевременно сообщит об окончании загрузки и завершит работу, не окончив полностью процесс разгрузки.

public class Queues {

private static final int STORAGE_SIZE = 10;

private static final int GOODS_NUMBER = 30;

private ArrayBlockingQueue<Stuff> storage;

private boolean loadFinished;

public Queues()

{

storage = new ArrayBlockingQueue<Stuff>(STORAGE_SIZE);

}

public void start() {

// запускаем потоки погрузки и разгрузки

Thread loader = new Loader();

loader.start();

Thread unloader = new Unloader();

unloader.start();

try

{

loader.join(); // ждем окончания погрузки

} catch (InterruptedException e)

{

}

loadFinished = true; // устанавливаем флаг, что погрузка закончилась

}

public class Loader extends Thread {

public void run()

{

try {

for (int i = 0; i < GOODS_NUMBER; i++) {

Thread.sleep(new Random().nextInt(300) + 100);

// загружаем новый товар

Stuff stuff = new Stuff(i+1);

storage.put(stuff);

System.out.println(String.format("Товар №%d загружен", stuff.getNumber()));

}

} catch (InterruptedException e) {

}

System.out.println("Загрузка товаров окончена");

}

}

public class Unloader extends Thread {

public void run()

{

try {

while (!isInterrupted()) {

Stuff stuff;

// разгружаем товар

if (loadFinished)

stuff = storage.poll();

else

stuff = storage.take();

if (stuff == null) // разгузка закончилась и в очереди больше ничего нет

break;

Thread.sleep(new Random().nextInt(700) + 200);

System.out.println(String.format("Товар №%d разгружен", stuff.getNumber()));

}

} catch (InterruptedException e) {

}

System.out.println("Разгрузка товаров окончена");

}

}

public class Stuff {

private int number;

/**

* @param number

*/

public Stuff(int number)

{

super();

this.number = number;

}

public int getNumber()

{

return number;

}

}

public static void main(String[] args) {

new Queues().start();

}

}

    1. Пример использования исполнителей

Исполнитель принимает на исполнение задачу, которая производится в отдельном потоке. Если у исполнения есть результат, то его можно получить, используя интерфейс Future.

public class Execs {

public static class FactorialCalculator implements Callable<Long> {

private int n;

public FactorialCalculator(int n)

{

super();

this.n = n;

}

@Override

public Long call() throws Exception

{

long result = 1;

for (int i = 1; i < n; i++ ) {

result *= i;

}

return result;

}

}

public static void main(String[] args) {

int n = new Scanner(System.in).nextInt();

ExecutorService executor = Executors.newSingleThreadExecutor();

Future<Long> result = executor.submit(new FactorialCalculator(n));

try

{

System.out.println("Результат: " + result.get());

} catch (InterruptedException e)

{

} catch (ExecutionException e)

{

e.printStackTrace();

}

executor.shutdown();

}

}

  1. Задания

    1. Вариант 1.

Реализовать программу, симулирующую процесс работы железнодорожного склада, на котором может храниться один из трех видов товаров: сыпучие, жидкие и скоропортящиеся.

К складу «подъезжает» ж/д состав с определенным количеством и типов вагонов и ожидает погрузку товаров со склада. С другой стороны к складу «подъезжают» автомобили с данными товарами, которые разгружаются на склад. Склад имеет ограниченную вместимость по каждому из видов товаров.

Одновременно может разгружаться только один автомобиль каждого вида. Остальные ожидают своей очереди.

Ж/д состав ожидает полную загрузку всех вагонов, остальные составы ждут своей очереди.

Программа должна иметь графический интерфейс, схематично визуализирующую процесс работы и следующие элементы, управляющие:

  • подъездом автомобиля с грузом пределенного типа

  • подъездом нового ж/д состава.

На экране должно отображаться события:

  • начало разгрузки автомобиля

  • окончания разгрузки автомобиля

  • начало загрузки состава

  • окончание загрузки состава.

Необходимо иметь ввиду, что вместимость вагонов и автомобилей различается.

Реализовать временные задержки для лучшей визуализации процесса.

    1. Вариант 2.

Реализовать похожую программу, что и в варианте 1 с одним отличием, что разгрузка происходит в обратном порядке — из ж/д состава в автомобили.

    1. Вариант 3.

Реализовать похожую программу, что и в варианте 1 с одним отличием, что в случае полной загрузки скоропортящихся товаров в ж/д состав, его загрузка считается законченной.

    1. Вариант 4.

а) Разработать программу-сервер, обрабатывающая запросы от клиентов по сети. Протокол и данные запросов и ответов может быть произвольным. Если обработка данных занимает слишком мало процессорного времени, то для большей наглядности в обработчик запросов необходимо вставить временные задержки.

Программа-сервер должна иметь пул потоков фиксированного размера для обработки запросов от клиента. Программа-сервер может не иметь графического интерфейса.

б) Разработать программу-клиента для тестирования сервера, устанавливающая с сервером одновременно N соединений. Программа должна иметь графический интерфейс, результаты, полученные от сервера должны выводиться пользователю.

В данных программах необходимо использовать исполнителей (Executors)

Соседние файлы в папке labs2