Java: fill the gaps
12.6K subscribers
7 photos
216 links
Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк

🔥Тот самый курс по многопочке🔥
https://fillthegaps.ru/mt

Комплименты, вопросы, предложения: @utki_letyat
Download Telegram
Channel created
Fairness. Честная многопоточность.

Одна из проблем многопоточного программирования называется starvation. Её суть в том, что поток не может получить доступ к общим ресурсам и продолжать работу. Так получается, если:
- у потока низкий приоритет,
- другие потоки захватывают доступ к критической секции быстрее,
- поток вызвал wait() у объекта, но notify() достаётся другим потокам.

Ситуация неприятная: ресурсы потока заняты, а задача не выполняется. Чтобы избежать проблем выше можно использовать средства синхронизации с флажком fairness = true. Например,
Lock lock = new ReentrantLock(true);

Что при этом происходит? И почему этот параметр по умолчанию false?
При fairness=true преимущество получает самый долго ожидающий поток. При этом вероятность starvation ощутимо снижается. Конкретная очередность не гарантируется, так как параметр не влияет на планировщик потоков в ОС. Пропускная способность при этом ухудшается в разы

Интересный факт:
tryLock() не обращает внимания на параметр fairness и постарается захватить блокировку, даже если в очереди стоят другие потоки.
tryLock(0, TimeUnit.SECONDS) учитывает fairness и при наличии других ожидающих потоков встанет в общую очередь.

Что же делать? Использовать флажок fairness или нет?
Если описанные выше проблемы возможны и критичны, надёжнее использовать tryLock с увеличивающимся временем ожидания и не полагаться на fairness.

#core
👍132🔥2
Как стать лучшим разработчиком

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

Нормальный разработчик решает проблемы по мере поступления, учится тому, что пригодится в работе, бессистемно читает статьи по разным темам.
Хороший разработчик углубляет текущие знания, смотрит лекции по другим технологиям, читает фундаментальные книги.

Лучший разработчик делает то же, что и хороший. Но не просто поглощает факты, а разбирается, почему всё работает именно так. Какие границы применимости у новых знаний. Чем один подход лучше другого.

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

Анализируйте то, что делаете. Даже если вы ещё джуниор или мидл, и задачи выглядят как «напиши это по подобию того». Посмотрите на задачу шире и постарайтесь понять, почему сделано так, а не иначе. Когда читаете статьи и смотрите лекции задавайте себе вопрос - как ещё решить исходную проблему? Когда мой вариант лучше варианта из статьи? Сначала будет казаться, что других достойных опций нет, но со временем вы будете видеть их всё чаще.

Мгновенного профита от такого процесса не будет, но если привычка закрепится — вы будете на голову выше своих коллег. Чем выше должность - тем больше принимаемых решений и тем важнее навык критического мышления.

В разработке ПО полно инертности. Однажды выбранные способы решения выбираются снова и снова. Thinking out of the box — самый редкий и ценный навык и над ним тоже нужно работать.

#soft_skills
👍222👎1🔥1
Бесполезная калибровка Thread.sleep
или как JDK создаёт иллюзию выбора.

Все знают метод sleep(long millis) у класса Thread. Он останавливает выполнение потока на заданное количество миллисекунд.
Также в классе есть похожий метод sleep(long millis, int nanos). Здравый смысл подсказывает, что это тот же sleep, только время приостановки задаётся точнее.

Документация к методу подтверждает нашу догадку:
...sleep for the specified number of milliseconds plus the specified number of nanoseconds.

Что тут ещё обсуждать? Расходимся!

Но всё же посмотрим в код. После проверок на валидность, видим следующие строки:
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
sleep(millis);

То есть прибавить 1 миллисекунду, если наносекунд больше 500к.
Или выставить паузу в 1 миллисекунду, если микросекунд 0, а наносекунд не 0.

У JVM доступен один нативный метод, который работает только с миллисекундами. Поэтому результат не очень удивляет. Но зачем тогда нужен второй метод?

#core
👍81🔥1
Виды многозадачности
Сегодня выйдем за пределы JVM и посмотрим на многопоточность на уровне ОС.

Многопоточность — когда в одном процессе параллельно работают несколько потоков.
Многозадачность — несколько процессов параллельно исполняются в ОС.
При этом параллельно — не значит одновременно. Процесс/поток использует ресурсы процессора некоторое время, потом выполнение прерывается, ОС сохраняет временные данные (контекст), а ресурсы переходят на другой процесс/поток. Загружается контекст другой задачи, и выполнение продолжается.

Многозадачность бывает двух типов:
1. Вытесняющая.
ОС выделяет кванты времени для каждой задачи и управляет их переключением. Так работают потоки в джаве, а также процессы в современных ОС.
не нужно думать о переключении задач, всё делает ОС
повисшая задача не блокирует остальные
сложная работа с общими ресурсами
сложно координировать связанные параллельные задачи

2. Кооперативная.
Программа/поток сами сигнализируют, что пора сохранить контекст и переключиться на другую задачу. Так были организованы ОС давным-давно. В прикладных программах эта модель реализуется через fibers – «легковесные потоки», которые исполняются на одном потоке ОС и имеют собственный планировщик.
переключение контекста происходит в 10-100 раз быстрее
проще работа с общими ресурсами, не нужно часто синхронизироваться
эффективная обработка некоторого типа задач
увеличенная сложность разработки
ошибка в одной задаче сильно влияет на другие, вплоть до остановки основного процесса

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

#теория
👍8🔥21