Уютное сообщество джавистов
2.04K subscribers
31 photos
41 links
Уютное сообщество джавистов - это хорошие материалы,задачки,
туториалы для проверки знаний и обратная связь от соратников по изучению.

@viktorreh
Download Telegram
Best practice: не использовать boolean параметры в методах

На вопрос выше сходу ответят только знатоки многопоточки. Остальные наверняка попытались придумать, что означает cancel(true), и в чём разница с cancel(false).

Метод Future#cancel — наглядная иллюстрация, почему boolean параметры в public методах не ок. Потому что непонятно, что означают true и false.

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

Даже если у параметров хорошие имена, итоговые true и false выглядят несимпатично и неудобно.

С private методами ситуация другая. Внутренняя реализация должна быть читаемой и понятной, но требования всё же менее жёсткие, чем у public методов. В private методах флажки допустимы, но увлекаться не стоит:)

Как исправить метод с boolean параметром?

1️⃣ Сделать два метода

и зашить "особенность" флажка в название. Необязательно дублировать реализацию — public методы могут под капотом вызывать private метод с флажком.

Так сделано, например, в классе HashMap для методов put(k,v) и putIfAbsent(k,v). Оба в итоге вызывают private метод putVal с флажком ifAbsent

2️⃣ Создать enum с двумя значениями и передавать его вместо флажка
enum ReplicateStatus {NO_REPLICATION, REPLICATE};
...
saveRequest(req, ReplicateStatus.REPLICATE);

Такой вариант предлагается в книге Effective Java (Item 51).

Выглядит лучше, чем флажки, но на практике такой способ встречается редко. Если enum нужен только для обозначения true/false, быстрее и проще сделать 2 метода с разными именами.

🔥 Ответ на вопрос перед постом — "невозможно определить".

Мы не знаем точно, начала ли задача выполнение до вызова cancel. Даже если задача стартовала, успех cancel зависит от кода внутри задачи. Поэтому итог непредсказуем🤷‍♀️

#полезное
IDEA: как не потерять важные места в коде

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

Раньше это делали так:
🔴 Ставили неактивный брейкпойнт в нужном месте. В принципе нормально, но иногда сложно вспомнить, что где находится
⭐️ Добавляли файл в favorites. Файл добавляется целиком, что не очень удобно

Затем в IDEA убрали favorites и добавили закладки. Супер удобно, ни одна важная строчка теперь не потеряется.

▫️ Курсор на нужной строке → F11 → появляется закладка
▫️ Правый щёлк по закладке → Rename bookmark… → ввести что-то осмысленное
▫️ Посмотреть закладки: View → Tool Windows → Bookmarks (или Shift + F11)
8 ошибок начинающих разработчиков

Рассмотрим типичную историю начинающего разработчика👶

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

В этих условиях у стажёра сформировался стиль написания кода.

После собеседования стажёр начинает работать в крупном проекте вместе с другими разработчиками. И здесь очень важно перестроиться: многие паттерны, нормальные в учебных проектах, уже не подходят.

В этом посте опишу 8 таких паттернов на простых примерах.

1️⃣ Процедурный стиль

Задача: получить список заказов пользователя. Новичок скорее всего напишет такой код:
List list = new ArrayList();
process(user, list);


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

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

Как лучше: использовать выходные параметры, не менять входные данные, давать осмысленные имена методам:
List orders = getOrders(user);


2️⃣ Сложные универсальные методы

Задача: по-разному считать скидку для новых пользователей и пользователей с картами лояльности.

Новички часто используют принцип Don't Repeat Yourself на максималках и пишут универсальный метод с кучей параметров и десятком if внутри:
getDiscount(user, true, true, limit, true)


Как лучше: сфокусированные методы для разных ситуаций
getDiscountNew(user);
getDiscountLoyal(user, limit)


3️⃣ Длинные методы

Сложно читать и тестировать, страшно менять.

4️⃣ Любовь к статическим методам

Как лучше: небольшие методы, связанные с конкретным классом. Связность ниже, ошибок меньше.

5️⃣ Сложное проектирование

Задача: завести три типа пользователей: новые, обычные и VIP. Новички скорее всего сделают интерфейс, 3 класса и статический класс с фабричными методами и билдером.

Как лучше: как можно проще. Например, один класс пользователя с полем Тип. Усложнять при реальной необходимости

PS Все "как лучше" не всегда лучше. Но думаю, идея понятна.

6️⃣ Нулевое или минимальное покрытие тестами

как следствие больших сложных методов и недостаточной инкапсуляции.

7️⃣ Низкий уровень ответственности

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

🔸 Непонятно, что происходит. Человек сидит и молчит до последнего, пока не спросишь статус задачи или про возможные трудности. Он умалчивает проблемы или переносит на других:

— Что с задачей, которую я тебе дала 3 дня назад?
— Я не понял, куда смотреть, потом меня HR позвал бумаги подписывать, потом я настраивал гит, увидел другую задачу и переключился на неё.


🔸 Код не решает проблему, а заметает симптомы:

— Приходил пустой параметр, и я выставил дефолтный. Тесты мешали сделать пул-реквест, и я их отключил.

8️⃣ Слабые коммуникативные навыки

— Как ты починил баг с расчётом ставки?
— Там через геттер фабричный метод нашёл, и потом докер с постгрёй поднял посмотреть, в логах был фильтр урезанный, я письмо отправил тебе в цц, но вроде скоуп не тот или тот, короче, запушил
— В чём была ошибка?
— Там два двоеточия вылезло
— Где?
— В дебаге
🤯


Эти ошибки ожидаемы в начале работы, я тоже их совершала🙂 Чем быстрее вы перестроитесь на командный стиль разработки, тем вероятнее пройдёте испытательный срок и быстрее вольётесь в проект.

#полезное
Как вредит ChatGPT

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

Нейросети — прекрасный инструмент, и в работе с ним есть два важных этапа:
👆 задать вопрос
✌️ провалидировать ответ

Второй пункт очень важен. ЧатЖПТ и другие нейросетки — не гигантская сеть знаний. Это искусственная модель, которая пытается угадать ответ, а задача пользователя — провалидировать его. Но бывает, что этап валидации пропускается, и мы получаем

Следствие 1: низкий уровень знаний после курсов

Иногда ученики курсов ленятся разбираться в непонятном. Тогда они спрашивают ответ у нейросети и сдают его на проверку.

Пользы от такого "обучения" нет. Лучше ошибиться и разобрать ошибку с преподавателем, чем получить формальный зачёт и забить не возможный пробел.

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

Так что скоро увидим больше выпускников курсов с формальным дипломом и поверхностными знаниями. Ситуация на рынке джунов и так печальная, а станет ещё хуже😔

✍️ Что делать:

Не используйте нейросети для обучения. Если что-то непонятно — спросите преподавателя, поищите статьи на хабре/baeldung, почитайте документацию.

Особенно это касается практики. Во многих вещах надо "набить руку", и в процессе работы всплывают все непонятные моменты. А готовый ответ выветрится из головы через секунду.

Следствие 2: низкое качество контента в "Java" каналах

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

Сейчас чаще появляются посты, сделанные при участии ChatGPT. Качество контента не выросло, но теперь в постах проскальзывают ошибки.

Парочка примеров:

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


🤔 Пост о методе compareAndSwap():
Такого метода в атомиках вообще нет. В описании снова находим противоречие — метод возвращает то ли результат операции, то ли текущее значение переменной.

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

При использовании нейросети человек отдаёт себе отчёт, что это нейросеть, и может засомневаться в ответе. А посты в "Java" канале реже подвергаются сомнению.

✍️ Что делать:

Отписаться от таких каналов. В интернете петабайты материалов для новичков, в которых точно нет ошибок. Даже устаревший текст лучше неверной информации.

И конечно, читать каналы разработчиков, которые пишут авторский контент и делятся опытом. Люди тоже ошибаются, но качество таких постов гораздо выше. Не забывайте про лайки и обратную связь, это правда очень мотивирует писать дальше🥰

#полезное
Не забывайте вовремя обновляться
Подборка викторин по Java.
Проверьте ваши знания вместе с qarocks.ru

Викторина по Java перечислениям Enums
Насколько хорошо вы знакомы с enum в Java? Давайте узнаем это с помощью викторины для начинающих!

Викторина по регулярным выражениям Java RegEx
Давайте проверим ваши знания о регулярных выражениях в Java!

Викторина по массивам в Java
Давайте проверим ваши знания о массивах в Java!

Викторина по типу String в Java
В этой викторине мы проверим ваши знания о строках в Java.

Викторина по методам Java
Давайте проверим ваши знания о методах в Java!

Викторина по интерфейсам в Java
Проверьте свои знания в интерфейсах на языке программирования Java с помощью нашей викторины.

Викторина по строкам в Java
Ответьте на вопросы нашей викторины, чтобы проверить свои знания по строкам на языке программирования Java.

Викторина по наследованию в Java
Проверьте свои знания в наследовании на языке программирования Java с нашей викториной!

Викторина по массивам в Java
Эта викторина из 10 вопросов поможет проверить ваши знания по массивам на языке программирования Java!

Викторина по типам данных в Java
Давайте проверим ваши знания и понимание различных типов данных в языке программирования Java.

#викторины #подборка

Надеемся на отличные результаты.
Хорошего дня всем!
🚀 Юнит-тестирование вашей Java-архитектуры 🚀

@archtests - это мощная библиотека Java, которая позволяет писать модульные тесты для обеспечения соблюдения архитектурных ограничений и правил в вашем коде.

https://archunit.org
💡Задача: Сумма вдоль столбцов

Условие: дается квадратная матрица, необходимо вычислить минимальную сумму вдоль столбца.

Есть условие на движение вдоль столбца есть ограничение: можно перемещаться на ячейку вниз лишь по диагонали или строго вниз.

Пример:

Ввод:
matrix = [[2,1,3],[6,5,4],[7,8,9]]
Вывод: 13
Объяснение: *во вложении

Решение
От JDBC до Spring Data: часть 1

Общение с базой данных связано с огромным количеством технологий — навскидку вспоминаем JDBC, JPA, Hibernate и Spring Data. Они тесно переплетены, и не всегда люди чётко понимают, что есть что и зачем нужно.

В ближайших постах разложу по полочкам основные технологии по работе с данными.

Почему всё так сложно? Почему нельзя сохранить всё как есть?

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

Чтобы данные пережили приложение, они записываются в постоянную память. Хранением и организацией данных занимается БД.

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

А ещё БД — это отдельное приложение. В итоге для сохранения/извлечения данных нужна куча дополнительной работы:
🔸 открыть соединение
🔸 составить SQL запрос
🔸 передать в запросе данные из приложения
🔸 преобразовать ответ БД в java объект
🔸 закрыть соединение

JDBC

— стандартные java методы, которые выполняют все пункты выше. Все инструменты по работе с БД под капотом используют как раз JDBC.

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

Spring JDBC

берёт на себя работу с соединениями. Разработчик всё так же составляет запросы, передаёт параметры и преобразует ответы в java объекты.

ORM

Object Relational Mapping — преобразование данных (mapping) из java объектов в сущности БД и обратно.

Формально, ORM — просто название процесса. В случае JDBC весь ОRМ разработчик делает вручную.

На практике под ORM подразумевают ORM библиотеку/фреймворк — какой-нибудь инструмент, который берёт на себя часть работы по запросам и преобразованию данных.

Hibernate

— самая популярная ORM библиотека. Составляет простые SQL запросы и преобразует данные. Упростил жизнь многим и заслужил их любовь❤️

В хибернейте не всё идеально:
▪️ Работа с соединениями (сессиями) остаётся на пользователе
▪️ Для корректной работы надо знать внутрянку (dirty session, как разруливаются отношения и тд).

Сложно не признать, что Hibernate великолепен. Ворвался на олимп ORM библиотек в 2001 году и до сих пор оттуда не слезает🏆

JPA

Сейчас большинство приложений базируются на спринге, но 10-15 лет назад приложения часто опирались на Java ЕЕ. В те года ORM Java ЕЕ выглядел сложно — для каждой сущности требовались несколько классов и кучка интерфейсов.

Hibernate выглядел привлекательно, но нельзя просто взять и добавить библиотеку в проект. Во вселенной Java EE всё работает через спецификации — стандартные интерфейсы.

Поэтому появилась новая спека по ORM — Java Persistence API или JPA. С небольшими отличиями почти полностью списана с хибернейта. Вскоре Hibernate подстроился под JPA и стал использоваться в Java EE.

Итого

⭐️ JDBC — базовое API по работе с БД
⭐️ ORM — преобразование данных между приложением и БД. На практике под “у нас на проекте ORM” имеют в виду, что используется ORM библиотека, например, Hibernate
⭐️ JPA — спецификация по ORM. Набор интерфейсов, аннотаций и описание, как всё должно работать. Не включает в себя конкретную реализацию
⭐️ Hibernate — популярная ORM библиотека, реализующая JPA

В следующем посте распишу вариации Spring Data, и почему материалы по хибернейт могут не соответствовать реальности.

#полезное
От JDBC до Spring Data: часть 2

В этом посте расскажу про популярные модули Spring Data и подскажу важный нюанс при изучении Hibernate.

Spring Data JPA

Hibernate вызвал вау-эффект тем, что взял на себя маппинг и простейшие SQL запросы.

Spring Data JPA пошёл дальше и избавил разработчика от унылых конфигов и возни с сессиями, плюс генерирует более сложные SQL запросы.

Всё очень круто (без шуток), но есть нюанс.

Ванильный Hibernate подразумевает, что пользователь знаком с деталями реализации — умело работает с кэшами 1 и 2 уровня, различает persist/save/merge, использует нужные типы данных и тд.

А вот JPA определяет только интерфейс доступа к данным. Поэтому в Spring Data JPA многие хибернейт фичи не используются.

Пример — ленивая загрузка коллекций и кэш 1 уровня. Spring Data в общем случае при каждом обращении к репозиторию создаёт новую сессию. Кэширования в итоге нет, а при загрузке коллекций ловим эксепшн.

Кэш 2 уровня и EntityGraph поправят ситуацию, но это уже продвинутый уровень:) Недостаточно пользоваться абстракцией "репозиторий", надо знать и Hibernate, и как Spring использует Hibernate.

Практический совет — если что-то читаете по хибернейту, уточняйте, как это работает в Spring Data и работает ли вообще.

Для простых сервисов Spring Data JPA существенно упрощает жизнь. Для сложных тоже, но требует больше знаний.

Spring Data JDBC

— альтернатива Spring Data JPA. Под капотом у него JDBC без посредничества Hibernate.

Интерфейс такой же — пользователь работает с репозиторием и размечает классы аннотациями типа @Id или @Column.

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

Отдельного внимания заслуживает работа с зависимыми сущностями в DDD стиле. А в этом докладе показан наглядный пример и больше различий Spring Data JPA/JDBC.

Важный момент! Не путайте две библиотеки:
🌸 Spring JDBC упрощает работу с соединениями. Запросы, маппинг сущностей, управление транзакциями пишет разработчик
🌹 Spring Data JDBC даёт следующий уровень абстрации — репозиторий. Работа c запросами, маппингом и транзациями упрощается за счёт аннотаций

MyBatis

часто упоминается как альтернатива Hibernate. Называет себя persistence framework, а не ORM, но занимается тем же — помогает писать меньше кода по перегону данных между БД и приложением.

Основное отличие MyBatis от хибернейта — все SQL-запросы пишутся явно, и внутри можно писать if и foreach блоки.

MyBatis в целом ничего, но редко встречается. Причины просты:
Нет Spring Data модуля, только Spring Boot Starter. Писать руками нужно гораздо больше
В MyBatis есть аннотации, но документация и большинство статей используют XML. Выглядит несовременно👨‍🦳

Итого

⭐️ Spring Data * берёт на себя конфиги, работу с сессиями, генерацию некоторых запросов
⭐️ Spring Data JPA упрощает работу с Hibernate
⭐️ Spring Data JDBC предлагает похожий интерфейс, но на основе JDBC
⭐️ MyBatis для тех, кто хочет чего-то другого

Что выбрать?

Функционально Spring Data JPA/JDBC и MyBatis похожи, но со своими нюансами. Адекватных и современных бенчмарков в интернете нет. Статьи вроде "Hibernate vs MyBatis" очень поверхностные, не тратьте на них время.

На практике выбор делается почти случайно. Что затащат в проект на старте, то и используется:)

#полезное
Ссылки на методы в Java

Лямбды в Java полезны во многих направлениях. Лямбда-выражения можно использовать для более простых задач, а лямбда-утверждения — для более сложных. Лямбды могут вызывать другие методы для текущего объекта (this) и объектов, которые находятся в области видимости, таких как текущий элемент итерации и конечная локальная переменная за пределами лямбды. Лямбду всегда можно упростить, поместив код в другой метод.

Читать статью
Data Wrangling Using Pandas, SQL, and Java

Автор:
Oswald Campesato
Год издания: 2023

#java #en

Скачать книгу
🗑 Понимание различных сборщиков мусора в Java:

🔵 Serial Garbage Collector: Лучший вариант для однопоточных приложений с небольшими кучами. Он использует один поток для выполнения как малых, так и больших сборок мусора, что приводит к значительным паузам, но минимальной нагрузке на систему.

🔵 Parallel Garbage Collector: Подходит для приложений с высокими требованиями к пропускной способности. Использует несколько потоков для выполнения как малых, так и больших сборок мусора, уменьшая время пауз, но при этом увеличивая использование CPU.

🔵 Concurrent Mark-Sweep (CMS) Garbage Collector: Разработан для минимизации пауз за счёт выполнения основной части работы по сборке мусора параллельно с выполнением приложений. Подходит для приложений, где критически важна низкая задержка.

🔵 G1 Garbage Collector: Сбалансированный сборщик мусора, который стремится обеспечить предсказуемое время пауз, разделяя кучу на регионы и выполняя сборку мусора поэтапно. Является хорошим выбором по умолчанию для большинства приложений.

🔵 Z Garbage Collector и Shenandoah: Сборщики мусора с ультранизкой задержкой, разработанные для работы с большими кучами. Основная часть работы по сборке мусора выполняется параллельно, что позволяет минимизировать время пауз даже при очень больших кучах.

👉 Уютное сообщество джавистов #java
Please open Telegram to view this post
VIEW IN TELEGRAM
Kotlin Design Patterns and Best Practices

Автор:
Alexey Soshin
Год издания: 2022

#kotlin #en

Скачать книгу
🤫 Некоторые популярные методы аутентификации

🔵 Базовая аутентификация:
Предполагает отправку имени пользователя и пароля с каждым запросом, но может быть менее безопасной без шифрования.
Подходит для простых приложений, где безопасность и шифрование не являются приоритетом, или при использовании защищенных соединений.

🔵 Аутентификация с помощью токенов:
Использует сгенерированные токены, такие как JSON Web Tokens (JWT), которые обмениваются между клиентом и сервером, обеспечивая повышенную безопасность без необходимости отправки учетных данных с каждым запросом.
Идеально подходит для более безопасных и масштабируемых систем.

🔵 Аутентификация OAuth:
Позволяет сторонним приложениям получать ограниченный доступ к ресурсам пользователя без раскрытия учетных данных, выдавая токены доступа после аутентификации пользователя.
Подходит для ситуаций, требующих контролируемого доступа к ресурсам пользователя сторонними приложениями или сервисами.

🔵 Аутентификация с использованием API-ключей:
Назначает уникальные ключи пользователям или приложениям, которые отправляются в заголовках или параметрах; несмотря на простоту, может не обладать всеми преимуществами безопасности, как методы на основе токенов или OAuth.
Удобна для простого контроля доступа в менее чувствительных средах или для предоставления доступа к определённым функциям без необходимости предоставления разрешений, привязанных к конкретному пользователю.

💬 Какой метод аутентификации вы считаете наиболее эффективным с точки зрения обеспечения безопасности и удобства использования в ваших приложениях?

👉 Уютное сообщество джавистов #java
Please open Telegram to view this post
VIEW IN TELEGRAM
⌨️ Управление доступом к членам класса

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

Существует 4 уровня доступа:

private
Указывает, что доступ возможен только в его собственном классе.

package-private (нет явного модификатора)
Указывает, что доступ только внутри своего собственного пакета.

protected
Указывает, что доступ возможен только внутри его собственного пакета (как в случае с package-private) и, кроме того, для подкласса его класса в другом пакете.

public
Указывает, что доступ возможен отовсюду.

👉 Уютное сообщество джавистов #java
Please open Telegram to view this post
VIEW IN TELEGRAM
🚫 Ключевые проблемы многопоточности

🔵 Состояние гонки (Race Conditions):

Ситуация, когда несколько потоков пытаются одновременно читать и записывать общие данные, что приводит к непредсказуемым результатам.
Пример: Представьте, что два человека пытаются одновременно снять деньги с одного банковского счета. Без должной координации они могут снять больше денег, чем доступно на счете.

🔵 Взаимные блокировки (Deadlocks):

Ситуация, когда два или более потока застревают в ожидании друг друга для освобождения ресурсов, что приводит к тупиковой ситуации.
Пример: Два человека держат предметы, которые нужны друг другу, и оба ждут, пока другой первый отдаст свой предмет.

🔵 Ошибки конкуренции (Concurrency Bugs):

Ошибки, возникающие из-за неправильной обработки взаимодействия потоков, часто проявляющиеся как случайные проблемы.
Пример: Если два работника пишут в один и тот же файл без координации, их работа может перемешаться.

🔵 Прерывание потока (Thread Interruption):

Основная проблема заключается в том, что сигнал на прерывание лишь уведомляет поток о необходимости остановки, но сам поток должен обработать этот сигнал и завершить свою работу самостоятельно.
Пример: Если вам нужно, чтобы рабочий остановился, вы посылаете ему сигнал "стоп". Но нет гарантий, что это случится.

🔵 Ошибки согласованности памяти (Memory Consistency Errors):

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

🔵 Соперничество за ресурсы (Resource Contention):

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

🔵 Голодание (Starvation):

Ситуация, когда потоку постоянно отказывают в доступе к ресурсам из-за приоритета других потоков.
Пример: Если одного работника постоянно обходят вниманием в пользу других, он никогда не сможет выполнить свою работу.

👉 Уютное сообщество джавистов #java
Please open Telegram to view this post
VIEW IN TELEGRAM
Spring Boot and Angular

Автор:
Devlin Basilan Duldulao
Год издания: 2022

#java #spring #en

Скачать книгу
Learning Java

Автор:
Loy Marc, Niemeyer Patrick, Leuck Daniel
Год издания: 2020

#java #en

Скачать книгу
The Java Module System

Автор:
Nicolai Parlog
Год издания: 2019

#java #en

Скачать книгу