Главная страница

5 блок. Вводвывод, доступ к файловой системе


Скачать 270.29 Kb.
Название5 блок. Вводвывод, доступ к файловой системе
Дата03.09.2022
Размер270.29 Kb.
Формат файлаdocx
Имя файлаJava 5 module.docx
ТипДокументы
#660115
страница1 из 3
  1   2   3

5 БЛОК. Ввод-вывод, доступ к файловой системе



ПОТОКИ

1. Иерархия потоков в Java?

Существует два вида потоков ввода/вывода: байтовые и символьные.

Смотри картинки выше 😊

2. Какие варианты порядка работы потоков бывают? (асинхронные и синхронные)

- Асинхронный - асинхронные (параллельные) потоки независимы друг от друга (один что-то считает, второй спит, третий выводит что-то на консоль, но друг с другом они не взаимодействуют.), за исключением случаев, когда бизнес-логика зависимости выполнения потоков определяется предусмотренными для этого средствами языка.
В процессе работы потоки часто используют общие ресурсы приложения, определённые вне потока. Если несколько потоков начнут одновременно вносить изменения в общий ресурс (представь, что несколько потоков записывают текст в одно и то же место — например, в текстовый файл или консоль. Этот файл или консоль в данном случае становится общим ресурсом. Потоки не знают о существовании друг друга, поэтому просто записывают всё, что успеют за то время, которое планировщик потоков им выделит.

), то результаты выполнения программы могут быть непредсказуемыми и даже привести к ошибке. Чтобы избежать подобной ситуации, потоки необходимо синхронизировать.
- Синхронизированный - блок кода может быть выполнен только одним потоком одновременно. Для этого в Java есть «mutex». Если мьютекс объекта находится в руках одного потока, другие потоки не смогут получить доступ к работе с этим объектом. Не нужно ничего делать, чтобы создать мьютекс: он уже встроен в класс Object, а значит, есть у каждого объекта в Java, достаточно пометить блок кода ключевым словом synchronized.

Если один поток зашёл внутрь блока кода, который помечен словом synchronized, он моментально захватывает мьютекс объекта, и все другие потоки, которые попытаются зайти в этот же блок или метод вынуждены ждать, пока предыдущий поток не завершит свою работу и не освободит монитор.
Можно использовать synchronized в своих классах определяя синхронизированные методы или блоки. Но нельзя использовать synchronized в переменных или атрибутах в определении класса.

public synchronized void swap() {}

Подробнее про синхронизацию можно посмотреть тут!

3. Что такое поток?

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


4. Что такое многопоточность?

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

5. Thread и Runnable, что выбрать? Зачем нужно два вида реализации многопоточности?

Реализация интерфейса Runnable используется в случаях, когда класс уже наследует какой-либо родительский класс и не позволяет расширить класс Thread. К тому же хорошим тоном программирования в Java считается реализация интерфейсов. Это связано с тем, что в Java может наследоваться только один родительский класс. Таким образом, унаследовав класс Thread, невозможно наследовать какой-либо другой класс.

Расширение класса Thread целесообразно использовать в случае необходимости переопределения других методов класса помимо метода run().

6. Что такое главный поток?

При запуске программы автоматически создаётся главный поток — который выполняет метод main(), (главный метод программы.) Программа завершается, когда главный поток останавливается.

Несмотря на то, что главный поток создаётся автоматически, им можно управлять. Для этого необходимо создать объект класса Thread вызовом метода currentThread().
В рамках главного потока могут создаваться(запускаться) дочерние потоки(подпотоки), в которых, в свою очередь также могут запускаться потоки, и т.д.

Потоки представляют собой классы, каждый из которых запускается от главного потока (метод main) и работает самостоятельно.

7. Как создать новый поток? (2 способа)

- Создать потомка класса Thread и переопределить его метод run(). Запустить при помощи start().

- Создать объект класса Thread, передав ему в конструкторе класс, реализующий интерфейс Runnable. Этот интерфейс содержит метод run(), который будет выполняться в новом потоке. После вызывается метод start() в результате чего запускается выполнение потока.

8. Методы управления потоками класса Thread (16 штук)

Класс Thread содержит несколько методов для управления потоками:

currentThread() - получить текущий поток выполнения

- long getId() - получение идентификатора потока;

- String getName() - получение имени потока;

- int getPriority() - получение приоритета потока;

- State getState() - определение состояния потока;

- void interrupt() - прерывание выполнения потока;

- boolean isAlive() - проверка, выполняется ли поток;

- boolean isDaemon() - проверка, является ли поток «daemon»;

- void join() - ожидание завершения потока;

- void join(millis) - ожидание millis миллисекунд завершения потока;

- void notify() - «пробуждение» отдельного потока, ожидающего «сигнала»;

- void notifyAll() - «пробуждение» всех потоков, ожидающих «сигнала»;

- void run() - запуск потока, если поток был создан с использованием интерфейса Runnable;

- void setDaemon(bool) - определение «daemon» потока;

- void setPriority(int) - определение приоритета потока;

- void sleep(int) - приостановка потока на заданное время;

- void start() - запуск потока.

- void wait() - приостановка потока, пока другой поток не вызовет метод notify();

- void wait(millis) - приостановка потока на millis миллисекунд или пока другой поток не вызовет метод notify();

9. Методы интерфейса Runnable? (1 метод)

Интерфейс содержит только один метод run().

Метод run() выполняется при запуске потока. После определения объекта Runnable он передается в один из конструкторов класса Thread.

10. Какие конструкторы имеет класс Thread? (7 штук)

- Thread()

- Thread(Runnable object)

- Thread(Runnable object, String name)

- Thread(String name)

- Thread(ThreadGroup group, Runnable object )

- Thread(ThreadGroup group, Runnable object , String name)

- Thread(ThreadGroup group, String name)

Где:

name – это имя, присваиваемое потоку;

object – это экземпляр класса реализующего интерфейс Runnable;

group – группа, к которой относится поток.

Если имя не присвоено, система сгенерирует уникальное имя в виде Thread-N, где N целое число.

11. Состояние потоков. Их жизненный цикл?



При выполнении программы объект Thread может находиться в одном из четырёх основных состояний: «новый», «работоспособный», «неработоспособный» и «пассивный». При создании потока он получает состояние «новый» (NEW) и не выполняется. Для перевода потока из состояния «новый» в «работоспособный» (RUNNABLE) следует выполнить метод start(), вызывающий метод run().
Поток может находиться в одном из состояний, соответствующих элементам статически вложенного перечисления Thread.State:

- NEW — поток создан, но еще не запущен;

- RUNNABLE — поток выполняется;

- BLOCKED — поток блокирован;

- WAITING — поток ждет окончания работы другого потока;

- TIMED_WAITING — поток некоторое время ждет окончания другого потока;

- TERMINATED — поток завершен.
Возможна ситуация, когда один поток изменил значение переменной, а второй не увидел этого изменения, потому что работал со своей, кэшированной копией переменной.

Ключевое слово volatile:

- Если объявить переменную z как volatile, изменения её значений в одном потоке всегда будут видны в другом потоке. Запись в volatile-переменные происходит раньше, чем чтение из них.

- Она всегда будет атомарно читаться и записываться. Даже если это 64-битные double или long.

- Java-машина не будет помещать её в кэш. Так что ситуация, когда 10 потоков работают со своими локальными копиями исключена.

11. Какие свойства у потока?

- id – идентификатор потока

- name – имя потока

- priority – приоритет потока

- daemon – поток-демон

Свойства потока не могут изменяться после запуска

12. Приоритеты потоков. Что к кему?

Планировщик потока определяет какой поток должен запуститься, основываясь на номере приоритета, который есть у каждого потока. Приоритет может принимать значения от 1 до 10. По умолчаанию, значение приоритета для потока равно 5.

getPriority() - испольуется для получения текущего значения приоритета потока.

setPriority() – Устанавливает приоритет потоку.

13. Как завершить работу потока? (3 способа)

- Поток завершится, когда закончит выполнение метода run() обратившись к методу interrupt().

- Поток может создать исключительное состояние или ошибку, которые не удастся перехватить

- Поток может вызвать один из нерекомендуемых методов (stop() или destroy()). Эти методы нерекомендуется использовать. При принудительной остановке (приостановке) потока, совершенно непонятно, что делать с ресурсами!

14. Какими бывают потоки в Java?

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

15. Что такое поток ввода и вывода?

Объект, из которого можно считать данные, называется потоком ввода, а объект, в который можно записывать данные, - потоком вывода.

16. Основные классы потоков ввода/вывода?

Байтовые: java.io.InputStream и java.io.OutputStream;

Символьные: java.io.Reader и java.io.Writer;

17. InputStream / OutputStream / Reader / Writer. Что делают? Отличия?

В основе всех классов, управляющих потоками байтов, находятся два абстрактных класса: InputStream (представляющий потоки ввода) и OutputStream (представляющий потоки вывода).

Но поскольку работать с байтами не очень удобно, то для работы с потоками символов Unicode были добавлены абстрактные классы Reader (для чтения потоков символов) и Writer (для записи потоков символов). В случае ошибок все методы класса передают исключение IOException.

Все остальные классы, работающие с потоками, являются наследниками этих абстрактных классов.





18. Какие интерфейсы реализуют InputStream / OutputStream / Reader / Writer?

- OutputStream реализует интерфейсы Closeable, Flushable, AutoCloseable

- InputStream реализует интерфейсы Closeable, AutoCloseable

- Reader реализует интерфейсы Closeable, AutoCloseable, Readable

- Writer реализует интерфейсы Closeable, Flushable, Appendable, AutoCloseable

19. Какие есть подклассы у класса InputStream?

- StringBufferInputStream - превращает строку (String) во входной поток данных InputStream.

- SequenceInputStream - сливает два или более потока InputStream в единый поток.

- PushbackInputStream - входной поток, поддерживающий однобайтовый возврат во входной поток.

- PrintStream - выходной поток, включающий методы print() и println().

- PipedInputStream - реализует понятие входного канала.

- ObjectInputStream - входной поток для объектов.

- InputStream - абстрактный класс, описывающий поток ввода.

- FilterInputStream - абстрактный класс, предоставляющий интерфейс для классов-надстроек, которые добавляют к существующим потокам полезные свойства.

- FileInputStream - для чтения информации из файла.

- DataInputStream - входной поток, включающий методы для чтения стандартных типов данных Java.

- ByteArrayInputStream - позволяет использовать буфер в памяти (массив байтов) в качестве источника данных для входного потока.

- BufferedInputStream - буферизированный входной поток.

20. Какие есть методы у класса InputStream? (6 штук)

- int available(): возвращает количество байтов, доступных для чтения в потоке без блокировки.

- void close(): закрывает поток.

- int read(): возвращает целочисленное представление следующего байта в потоке. Когда в потоке не останется доступных для чтения байтов, данный метод возвратит число -1.

- int read(byte[] buffer): считывает байты из потока в массив buffer. После чтения возвращает число считанных байтов. Если ни одного байта не было считано, то возвращается число -1.

- int read(byte[] buffer, int offset, int length): считывает некоторое количество байтов, равное length, из потока в массив buffer. При этом считанные байты помещаются в массиве, начиная со смещения offset, то есть с элемента buffer[offset]. Метод возвращает число успешно прочитанных байтов.

- long skip(long number): пропускает в потоке при чтении некоторое количество байт, которое равно number.
Отличие available от read

.available() не блокирует поток выполнения при отсутствии данных , а .read() - блокирует.

.available() возвращает примерное количество доступных для чтения байтов, а .read(byte[] b) - количество считанных в буфер (массив байтов), от -1 при достижении конца потока данных и до размера массива (b.length).

.available() лишь проверяет наличие данных, а .read() - их считывает.

21. Какие есть подклассы у класса OutputStream? (6 штук)

- ByteArrayOutputStream — это запись байтов в память byte[].

- FileOutputStream — это запись байтов в File

- FilterOutputStream — это общий суперкласс для более специфических выходных потоков, которые заранее манипулируют данными, такими как encryption/decryption, вычисление контрольной суммы, кодировка символов, сжатие и т. д.

- ObjectOutputStream для записи полноценных Java типов и объектов в сериализованной форме в байтовый поток. Он в основном позволяет конвертировать сложные объекты Java в необработанные байты и наоборот.

- OutputStream- это просто общий абстрактный класс этих потоков. Вы все равно не сможете его построить. Однако вы можете заявить против этого.

- PipedOutputStream предназначен для того , чтобы иметь возможность писать в другой InputStream в трубе, чтобы другая сторона могла читать их из этого InputStream.
  1   2   3


написать администратору сайта