- •Краткая историческая справка.
- •Преимущества языка 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.
Синхронизация потоков с помощью оператора synchronized.
Выше мы рассматривали пример взаимодействия двух потоков, когда они поочередно пользовались доступом к одному и тому же ресурсу, то есть выводили символы на экран.
Из-за неполной синхронизации потоков было заметно, что очередность вывода нарушается. Происходит это потому, что переключение между потоками происходит быстрее, чем выполняется цикл (у нас там внутри цикла еще и задержка в 5мс.), поэтому пока один поток выполняет одну - две итерации цикла, второй поток тоже успевает воспользоваться ресурсом один или два раза подряд.
Драйвер вывода на экран в данном случае выступает как общий ресурс, за доступ к которому конкурируют два потока и наша задача синхронизировать потоки таким образом, чтобы пока один поток производит вывод на экран, другой поток ожидал своей очереди и не пытался захватить ресурс.
Для использования синхронизации, нужно заключить ресурсную часть кода и сам блокируемый ресурс в специальный оператор:
synchronized(ресурс) { код_с_доступом_к_ресурсу }
Переделаем программу так, чтобы включить ресурсную часть кода в оператор синхронизации:
static class Print_scr {
public Print_scr() { } // конструктор класса
public void print(String str) {
System.out.print(str + " ");
} }
static class MyThread implements Runnable {
private String str;
private Print_scr sc;
MyThread(String s, Print_scr p) {
str = s; sc = p;
}
public void run() {
synchronized(sc){
for(int i = 0; i < 10; i++) {
try {
Thread.sleep(5);
} catch (InterruptedException e) { }
sc.print(str + " ");
//System.out.print(str + " "); // прежний способ вывода отключен
}
System.out.print(" ");
System.out.print(" \n");
}
}
}
public static void main(String[] args) {
Print_scr sc = new Print_scr();
new Thread(new MyThread("1", sc), "T1").start();
new Thread(new MyThread("2", sc), "T1").start();
}
В данном случае мы специально создали некий класс Print_scr, который делает вывод на экран с помошью своей функции print(String str). Доступ к этому классу является ресурсным и ссылку на него мы передаем внутрь создаваемого потока через его конструктор. Блок кода с циклом for мы заключили в оператор синхронизации и пометили, что доступ к объекту sc является ресурсным, поместив его в круглые скобки оператора synchronized:
synchronized(sc){
…
for …
}
Теперь пока в одном потоке не отработает цикл for, другой поток не сможет завладеть объектом sc, чтобы осуществить вывод на экран.
Как и следовало ожидать, после запуска, программа напечатает:
1 1 1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2 2
То есть, теперь потоки отрабатывают вывод на экран строго последовательно, один за другим.
