- •Краткая историческая справка.
- •Преимущества языка Java.
- •Недостатки java:
- •Лекция 2. Этапы разработки java-приложений. Этапы разработки java-приложений.
- •Установка jdk.
- •Инсталляция исходных кодов библиотек
- •Инсталляция пакета документации.
- •Тестирование правильности установки и создание простейшей программы
- •Визуальные среды программирования.
- •Лекция 3. Переменные и типы данных. Переменные и типы данных.
- •Подробности о примитивных типах.
- •Лекция 4. Операторы и функции. Операторы и функции.
- •Операторы ветвлений и циклов.
- •Оператор цикла while.
- •Оператор цикла for.
- •Лекция 5. Объектно ориентированное программирование Объектно ориентированное программирование.
- •Определение объекта.
- •Инкапсуляция.
- •Наследование.
- •Полиморфизм (перегрузка).
- •Пример ооп – программы.
- •Отличие перегрузки функций от переопределения.
- •Отличие классов от интерфейсов.
- •Лекция 6. Массивы и строки. Массивы и строки.
- •Многомерные массивы.
- •Приведение типов и динамические массивы.
- •Строки в java.
- •Лекция 7. Организация ввода-вывода данных Организация ввода-вывода данных.
- •Функции стандартной библиотеки ввода/вывода.
- •Новая библиотека ввода/вывода.
- •Классы потокового ввода/вывода из пакета java.Io.
- •Лекция 8. Обработка исключений. Обработка исключений.
- •Классификация исключений.
- •Перехват исключений блоками try/catch.
- •Самостоятельное выбрасывание исключений.
- •Разработка собственных классов исключений.
- •Лекция 9. Потоки. Потоки.
- •1. Cпециальный класс Thread.
- •2. Реализация интерфейса Runnable.
- •Выбор между использованием класса Thread и интерфейса Runnable.
- •Синхронизация потоков с помощью оператора synchronized.
- •Синхронизация потоков с помощью семафоров.
- •Лекция 10. Подключаемые библиотеки java. Подключаемые библиотеки java.
- •Библиотека awt
- •Внутреннее устройство системы обработки событий awt.
- •Библиотека Swing.
Синхронизация потоков с помощью семафоров.
В примере выше мы рассматривали вариант тотальной блокировки ресурса, когда ресурс оставался блокированным, пока один из потоков полностью не закончит с ним работу. Но что делать, если нам не нужно, чтобы поток блокировал ресурс на длительное время? Что если мы хотим заставить потоки выкидывать данные на экран строго по очереди?
Что если мы не хотим, чтобы ресурс блокировался монопольно? Что, если нам достаточно, чтобы с ресурсом в каждый момент времени работало ограниченное число потоков? Скажем, штук 5 и не больше?
Здесь нам на помощь придут специальные конструкции языка, называемые семафорами.
Механизм, который используется в большинстве современных ОС для подобной синхронизации потоков, называется семафор. Принцип действия основан на временном монопольном блокировании потоком какого-либа ресурса и ограничении доступа всех остальных потоков к нему до тех пор, пока он ему нужен. Похоже на действие семафора, который блокирует трафик на перекрестке, пуская пересекающиеся потоки машин с разных направлений строго по очереди. При этом, продолжительность блокирования ресурса и освобождение его определяется самим потоком.
Изменим программу таким образом, чтобы использовать семафоры.
static class Print_scr {
int x = 1;
public Print_scr() { }
public void print(String str) {
System.out.print(str + " ");
}
}
static class MyThread implements Runnable {
private String str;
private Print_scr ps;
private Semaphore sm;
MyThread(String s, Semaphore sem, Print_scr p) {
str = s; ps = p; sm = sem;
}
public void run() {
for(int i = 0; i < 10; i++) {
try {
sm.acquire();
if(ps.x == Integer.parseInt(str)) {
ps.print(str + " ");
if(Integer.parseInt(str) == 1) ps.x = 2;
if(Integer.parseInt(str) == 2) ps.x = 1;
}
sm.release();
Thread.sleep(5);
} catch (InterruptedException e) {}
}
System.out.print(" \n");
}
}
public static void main(String[] args) {
Semaphore sem = new Semaphore(1); // создаем семафор с 1 разрешением
Print_scr sc = new Print_scr();
new Thread(new MyThread("1", sem, sc), "T1").start();
new Thread(new MyThread("2", sem, sc), "T1").start();
}
Здесь мы добавили в класс Print_scr специальное поле int x, которое определяет какой поток в данное время может воспользоваться ресурсом. Далее мы изменили класс MyThread, добавив в него переменную, которая будет содержать наш семафор, кроме того мы встроили блок, который будет проверять состояние переменной ps.x и переключать состояние этой переменной. Функция sm.acquire() определяет состояние семафора и если он открыт, захватывает его. Функция sm.release() освобождает семафор, когда он больше не нужен. Ну и в заключение, в функции main() мы создаем экземпляр семафора и передаем этот экземпляр внутрь классов потоков. Обратите внимание, что сигнатуру вызова конструктора класса потока мы тоже доработали, чтобы он принимал ссылку на объект семафора. Кстати, семафор, который имеет разрешение только на один поток (как у нас здесь), в терминологии многопоточного программирования называется "мъютекс".
В итоге на экране будет напечатано:
2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2
