Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Пример 6.4. Канал обмена информацией




class Target extends Thread {

private PipedReader pr;

Target(PipedWriter pw) {

try { pr = new PipedReader(pw); }

catch(IOException e) {

System.err.println("From Target(): " + e);

}

}

PipedReader getStream(){ return pr; }

public void run() {

while(true) {

try { System.out.println("Reading: " + pr.read()); }

catch(IOException e) {

System.out.println("The job's finished.");

System.exit(0);

}

}

}

}

 

class Source extends Thread {

private PipedWriter pw;

Source() { pw = new PipedWriter(); }

PipedWriter getStream() { return pw;}

public void run() {

for (int k = 0; k < 10; k++) {

try {

pw.write(k);

System.out.println("Writing: " + k);

}

catch(Exception e) {

System.err.println("From Source.run(): " + e);

}

}

}

}

 

public class Main {

public static void main(String[] args) throws IOException {

Source s = new Source();

Target t = new Target(s.getStream());

s.start();

t.start();

}

}

 

Сериализация объектов. Методы классов ObjectInputStream и ObjectOutputStream позволяют прочитать из входного байтового потока или записать в выходной байтовый поток данные сложных типов — объекты, массивы, строки.

Процесс записи объекта в выходной поток получил название сериализации (serialization), а чтения объекта из входного потока и восстановления его в оперативной памяти — десериализации (deserialization).

Сериализации можно подвергнуть объекты, которые реализует интерфейс Serializable. Этот интерфейс не содержит ни полей, ни методов. По сути дела это только пометка, разрешающая сериализацию класса.

class A implements Serializabie{...}

Для сериализации достаточно создать объект класса ObjectOutputStream, связав его с выходным потоком, и выводить в этот поток объекты методом writeObject().

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

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

Все классы объектов, входящих в такое сериализуемое множество, а также все их внутренние классы, должны реализовать интерфейс Serializable, иначе будет выброшено исключение NotSerializableException и процесс сериализации прервется.

Десериализация происходит так же просто, как и сериализация. Нужно только соблюдать порядок чтения элементов потока.

В примере 6.5 мы создаем объект класса GregorianCalendar с текущей датой и временем, сериализуем его в файл date.ser, через три секунды десериализуем и сравниваем с текущим временем.

Пример 6.5. Сериализация объекта

import java.util.*;

 

class SerDatef {

public static void main(String[] args) throws Exception {

GregorianCalendar d = new GregorianCalendar();

ObjectOutputStream oos = new ObjectOutputStream(

new FileOutputStream("date.ser"));

oos.writeObject(d);

oos.flush();

oos.close();

Thread.sleep(3000);

 

ObjectInputStream ois = new ObjectInputStream(

new FileInputStream("date.ser"));

GregorianCalendar oldDate = (GregorianCalendar)ois.readObject();

ois.close();

GregorianCalendar newDate = new GregorianCalendar();

System.out.println("Old time = " +

oldDate.get(Calendar.HOUR) +

":" + oldDate.get(Calendar.MINUTE) +

":" + oldDate.get(Calendar.SECOND) +

"\nNew time = " + newDate.get(Calendar.HOUR) +

":" + newDate.get(Calendar.MINUTE) +

":" + newDate.get(Calendar.SECOND));

}

}

 

Метод writeObject() не записывает в выходной поток поля, помеченные static и transient. Впрочем, это положение можно изменить, переопределив метод writeObject() или задав список сериализуемых полей.

Вообще процесс сериализации можно полностью настроить под свои нужды, переопределив методы ввода/вывода и воспользовавшись вспомогательными классами. Можно даже взять весь процесс на себя, реализовав не интерфейс Serializable, а интерфейс Externalizable, но тогда придется реализовать методы readExternal () и writeExternal (), выполняющие ввод/вывод.

 

Файловые диалоги. При работе с файлами часто требуются стандартные файловые диалоги. Библиотека Swing предлагает класс JFileChooser для реализации этого функционала.

JFileChooser fc = new JFileChooser();

fc.showOpenDialog(frame);

File selFile = fc.getSelectedFile();

fc.showSaveDialog(frame);

selFile = fc.getSelectedFile();

 

Практические задания

 

1. Изучить особенности реализации потоков ввода-вывода в Java.

2. Доработать программу, созданную в лабораторных работах № 2-5:

1) добавить в главное меню команду «Консоль». По этой команде должно появляться немодальное диалоговое окно с многострочным текстовым полем, занимающим всю область окна. В это окно можно вводить команды по варианту. В это же окно выводится реакция программы на команду;

2) для передачи команды в основное окно программы использовать каналы ввода-вывода;

3) создать конфигурационный файл для программы. В конфигурационный файл должны сохраняться все настройки симуляции, т.е. все данные и состояния, которые задаются в панели управления программы. Конфигурационный файл должен читаться при запуске программы и записываться при выходе. Формат файла текстовый;

4) добавить в главное меню команды «Загрузить» и «Сохранить». Команда «Сохранить» вызывает сериализацию всех «живых» объектов в ней. Команда «Загрузить» останавливает текущую симуляцию (если симуляция запущена) и загружает объекты из выбранного файла. После открытия симуляцию можно запустить, загруженные объекты должны вести себя естественно;

5) использовать стандартные файловые диалоги.

 

Вариант 1

Реализовать в консоли команды «Старт» и «Стоп» симуляции. Кнопки в интерфейсе должны вести себя так же, как если бы нажимали их, а не исполняли команды (блокироваться по очереди).

Вариант 2

Реализовать в консоли команду «Вернуть количество живых пчел-рабочих/трутней». Как параметр в команду должен передаваться идентификатор вида объекта.

Вариант 3

Реализовать в консоли команды «Установить вероятность рождения золотых рыбок» и «Получить вероятность рождения золотых рыбок». Как параметр в команду установки должно передаваться значение вероятности. Полученная вероятность должна выводиться на консоль.

Вариант 4

Реализовать в консоли команду «Сократить число кроликов-альбиносов на N%». Как параметр в команду должно передаваться значение N%.

Вариант 5

Реализовать в консоли команды «Остановить интеллектуальное поведение объектов» и «Продолжить интеллектуальное поведение объектов». Команда «Остановить» - останавливает поток расчета интеллекта объектов, а команда «Продолжить» - возобновляет расчет после остановки.

Вариант 6

Реализовать в консоли команду «Уволить всех менеджеров» и «Нанять N новых менеджеров». Первая команда удаляет всех менеджеров из симуляции (новые продолжают генерироваться), вторая – генерирует N новых менеджеров. N – параметр команды.

Вариант 7

Реализовать в консоли команды «Установить вероятность генерации капитальных домов» и «Получить вероятность генерации капитальных домов». Как параметр в команду установки должно передаваться значение вероятности. Полученная вероятность должна выводиться на консоль.

Вариант 8

Реализовать в консоли команду «Сократить число мотоциклов на N%». Как параметр в команду должно передаваться значение N%.

Вариант 9

Реализовать в консоли команды «Показывать время симуляции» и «Скрывать время симуляции». Чекбокс в интерфейсе должен вести себя так же, как если бы использовали его, а не исполняли команды (галочка появляется/исчезает).

Вариант 10

Реализовать в консоли команду «Вернуть количество существующих юридических/физических лиц в картотеке». Как параметр в команду должен передаваться идентификатор вида объекта.

 

Вопросы для самопроверки

 

1. Что такое потоки ввода-вывода и для чего они нужны?

2. Какие классы Java являются базовыми для работы с потоками?

3. В чем разница между байтовыми и символьными потоками?

4. Какие стандартные потоки ввода-вывода существуют в Java, каково их назначение? На базе каких классов создаются стандартные потоки?

5. Чем является поток System.in, System.out, System.err? Какими методами чаще всего пользуются при работе с этим потоком?

6. Как создать файловый поток для чтения и записи данных?

7. В чем заключается особенность создания потока, связанного с локальным файлом?

8. Как создать поток для форматированного обмена данными, связанного с локальным файлом?

9. Как добавить буферизацию для потока форматированного обмена данными, связанного с локальным файлом?

10. За счет чего буферизация ускоряет работу приложений с потоками?

11. Когда применяется принудительный сброс буферов?

12. Для выполнения каких операций применяется класс File?

13. Для чего предназначен класс RandomAccessFile? Чем он отличается от потоков ввода и вывода?

14. Как организовать передачу объектов через потоки ввода-вывода?

15. Что такое сериализация объектов? Что такое десериализация объектов?

16. Как объявить класс сериализуемым?

17. Какие поля класса не сериализуются?

18. Как передаются данные между потоками в многопоточном приложении?

 

 

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...