Получи случайную криптовалюту за регистрацию!

Java: fill the gaps

Логотип телеграм канала @java_fillthegaps — Java: fill the gaps J
Логотип телеграм канала @java_fillthegaps — Java: fill the gaps
Адрес канала: @java_fillthegaps
Категории: Технологии
Язык: Русский
Количество подписчиков: 10.33K
Описание канала:

Привет! Меня зовут Диана, и я занимаюсь java разработкой с 2013г.
Делюсь опытом/знаниями по темам:
- Java Core
- Вопросы с собеседований
- Best practices
Комплименты, вопросы, предложения: @utki_letyat

Рейтинги и Отзывы

4.50

2 отзыва

Оценить канал java_fillthegaps и оставить отзыв — могут только зарегестрированные пользователи. Все отзывы проходят модерацию.

5 звезд

1

4 звезд

1

3 звезд

0

2 звезд

0

1 звезд

0


Последние сообщения 15

2021-07-09 19:00:04 Набор на курс завершён!
Спасибо всем, кто присоединился
Спасибо всем, кто не отписался
1.0K viewsedited  16:00
Открыть/Комментировать
2021-07-08 09:00:24 Вам в какую очередь?

Канал всё-таки полезный, поэтому приоткрою одну тему, которую подробно разбираем на курсе.

В пакете java.util.concurrent доступно 7 очередей. Самые простые из них это
ArrayBlockingQueue
LinkedBlockingQueue
ConcurrentLinkedQueue

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

Часть 1: внутреннее устройство

По названию класса легко предположить, что одна реализация сделана на основе массива, а две - с помощью связного списка.

Что это даёт? По сути - ничего.
Вспомним 2 списка с похожим строением - ArrayList и LinkedList. В первом легко искать элемент по индексу, во втором - вставлять и удалять элемент из середины списка.
Для очереди это не важно, потому что нас интересует только работа с началом и концом очереди.

Часть 2: механизм синхронизации

А здесь уже интереснее:
ArrayBQ использует один ReentrantLock
LinkedBQ - два ReentrantLock: один для начала очереди, другой - для конца
ConcurrentLQ использует CAS операции для обновления крайних элементов

Давайте попарно сравним их между собой

ArrayBQ и LinkedBQ

Отдельные локи для начала и конца очереди в LinkedBQ хорошо работают, когда начало очереди не совпадает с концом. То есть в очереди всегда что-то есть. С двумя локами с очередью в каждый момент времени могут работать два потока.

Если размер колеблется около нуля, то поддерживать два лока слишком затратно, гораздо проще работать с одним локом на всю очередь. Это вариант ArrayBQ.

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

LinkedBQ и ConcurrentLQ

Допустим, наша очередь никогда не пустует. Что лучше - два ReentrantLock или две CAS операции?

Здесь разница в методах, которые нам нужны.

CAS операции обновляют только сами элементы - начало и конец очереди.

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

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

Поэтому критерий выбора очереди №2: необходимые методы и ограничения на размер

А что на практике?

Насколько сильно эти различия влияют на пропускную способность? При какой нагрузке разница становится заметна? Чем ещё отличаются очереди?

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

Набор закрывается в пятницу. Записывайтесь, пока есть места:
https://fillthegaps.ru/mt2
1.5K views06:00
Открыть/Комментировать
2021-07-05 09:00:14 Началась последняя неделя набора на Тот Самый Курс

Must have для разработчиков, которые мало работали с многопоточкой, но готовы закрыть этот пробел за 2 месяца.

Прочтите отзыв участника первого потока:

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

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

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

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

++ отличная атмосфера на курсе. Как будто бы получаешь объяснения от самого себя из той версии будущего, где ты в сложной теме разобрался. :D

+ высокая плотность занятий. Казалось бы, много ли можно уложить в 10-20 минут лекции плюс задания к ней? Оказывается, много.

- были небольшие шероховатости по наполнению лекций (напр., иногда важные моменты проговаривались голосом, но отсутствовали на слайдах) и по формулировке отдельных вопросов.
- Сама платформа неидеальная: было несколько случаев, когда отправленный текстовый ответ терялся. На такой случай развернутые ответы лучше писать и сохранять у себя локально, в текстовом файле.

В целом, курс превзошел все возможные ожидания. Спасибо огромное!

Присоединяйтесь, стартуем уже в следующий понедельник
https://fillthegaps.ru/mt2
1.5K views06:00
Открыть/Комментировать
2021-07-02 09:00:14 Популярные вопросы по поводу курса

Я сеньор, читал Java Concurrency in practice и прошёл курсы на курсере, мне будет интересно?

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

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

Я с многопоточкой никогда не работал, только на собеседованиях рассказывал, мне подойдёт?

Цель курса - максимально подготовить вас к реальным задачам. Если вы знаете основы многопоточки, как написать сервис на Spring и у вас есть пара лет опыта - можно идти на курс.

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

У меня летом отпуск, я успею пройти курс?

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

Может моя компания оплатить курс?

Да, пусть ваш HR напишет на diana@fillthegaps.ru

Осталось всего 9 мест на тарифе с обратной связью.

Записывайтесь: https://fillthegaps.ru/mt2
1.6K views06:00
Открыть/Комментировать
2021-06-30 09:00:18 Набор на второй поток

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

Курс понравился и мне, и ученикам, поэтому открываю набор на второй поток. Если вам не нужно ничего объяснять, то запись тут.

Почему эта тема?

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

- Но у нас на проекте нет многопоточки!

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

Вторая причина, по которой я решила сделать курс - это слабое знание java.util.concurrent среди разработчиков.

Это хорошо видно на собеседованиях. На стандартные вопросы все отвечают бодро, но шаг в сторону или вопрос на понимание вызывают ужас и смятение.

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

Третья причина - нет цельных и актуальных материалов по этой теме. Большинство ограничивается рассказом про поток и экзекьюторы. Во времена java 5 это были топовые знания, но в 2021 требуется другое. Я собрала и упаковала свой опыт, лучшие практики и популярные ошибки в двухмесячный курс. Рассказываю всё как есть и простым языком.

Кому подойдёт?

Вы знаете основы многопоточности, но понимаете, что этого недостаточно
Вы хотите знать лучшие практики и основные ошибки, чтобы уверенно решать задачи
Хотите проходить сложные собеседования и вписываться в интересные проекты
Готовы на интенсивную работу в течение 8 недель

Старт: 12 июля
Длительность: 8 недель

С обратной связью - 15 мест
Без обратной связи - 12 мест

Программа, отзывы и остальные детали тут:
https://fillthegaps.ru/mt2

Записываемся
1.7K views06:00
Открыть/Комментировать
2021-06-25 09:00:05 Mutation testing: тесты на тесты

Фраза "нужны тесты на тесты" на проектах встречается часто. Звучит как шутка, но проблема за этим стоит серьёзная.

Тесты есть, но насколько хорошо они тестируют приложение? Когда что-то поменяется и сломается, узнаем ли мы об этом? Нет ли ошибок в самих тестах? Чем больше проект, тем насущнее эта проблема.

Test Coverage - сомнительная метрика. Высокий test coverage означает только, что в тестах участвует много кода.

В этом посте я расскажу о mutation testing. В чём суть, возможные минусы и как использовать подход mutation testing уже сейчас.

Идея

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

Пример: тестируется метод
return m > 10;

Написали для него тесты:
m = 0, ожидаем false
m = 100, ожидаем true

Фреймворк поменяет код на m ≥ 10, и ни один тест не упадёт. Значит, текущих тестов недостаточно, нужно проверить условие m = 10

Практика

Для JVM языков по факту есть только один фреймворк Pitest с двумя опциями - Gregor and Descartes.

Как работает:
Запускает тесты и анализирует test coverage. Если код не покрыт тестами, то нет смысла мутировать его.

Составляет список мутаций. Здесь два варианта:
Gregor тестирует по максимуму, в том числе геттеры и сеттеры
Descartes использует меньше вариаций, но работает быстрее

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

Минусы

Проверяются только несложные изменения бизнес-логики

Долго выполняется: от 10 минут до 6 часов. Для популярных библиотек результаты такие

Сложно читать результаты и понять, каких тестов не хватает. Связано это с тем, что фреймворк работает не с исходным кодом, а с байт-кодом

Gregor плохо совместим с Kotlin и проверяет конструкции, недопустимые на уровне языка. Приходится либо терпеть множество предупреждений, либо исключать некоторые проверки и рисковать бизнес-логикой. Либо использовать Descartes

Слабо развивается и выглядит как pet project

Непонятно как встроить в CI. Так как возможны ложноположительные результаты, репорты нужно проверять вручную. Можно оставить как необязательную опцию для самых мнительных, но проверка занимает много времени и вряд ли будет востребована

Итог: идея интересная и перспективная, но слабо развивается на практике.

Хозяйке на заметку

Подход mutation testing подойдёт для проверки тестов сложного или критичного участка кода:

Поменяйте условие
Верните константу в метод
Удалите тело в void методе
Поменяйте методы местами
Уберите инкремент
Верните null
Поменяйте бизнес-логику

И запустите тесты. Если падают - значит код протестирован хорошо. Если нет - допишите тесты. Главное - вернуть потом изменения обратно
1.5K views06:00
Открыть/Комментировать
2021-06-23 09:00:18 JVM Report 2020

Израильская компания Snyk каждый год опрашивает разработчиков о проектах и технологиях. В этом году в выборке 60% участников из Европы, 19% из США, на Россию и Азию пришлось 12%. Хороший шанс посмотреть, что там у других и на картину в целом

Полный отчёт доступен тут, а я расскажу самое интересное

Самый популярный JVM язык:
Однозначно, java. Используется на 91% проектов

31% используют в проектах несколько языков. Среди них:
17% Kotlin
13% Groovy
10% Scala
8,4% Closure

Версия java в продакшене:
61% Java 11
59% Java 8
11% Java 15

40% опрошенных используют несколько версий
30% используют Java 8 и Java 11

Какая JDK используется в продакшене:
44% AdoptOpenJDK
28% Oracle OpenJDK
23% Oracle JDK
15% Azul Zulu

37% участников используют 2 JDK, а 12.5% - три и больше.

Как собирается приложение:
76% Maven
38% Gradle
12% Ant

Основной фреймворк разработки:
58% Spring Boot
29% Spring MVC
24% Java EE
13% Jakarta EE
11% Quarkus
5% Micronaut

16% не пользуются фреймворками вообще

Самая популярная IDE:
72% IDEA
24% Eclipse
23% Visual Studio Code (2% в прошлом году)
13% Apache NetBeans (1% в прошлом году)

51% ответили, что пользуются несколькими IDE

По сравнению с прошлым годом Java 11 используется на 40% чаще, а IDEA и Kotlin уверенно укрепляют позиции
2.0K viewsedited  06:00
Открыть/Комментировать
2021-06-17 09:00:51 Intellij IDEA: пиши код как ниндзя

Успех за быстрыми. Когда решение найдено, его нужно тут же реализовать. Поэтому скорость набора кода должна стремится к скорости мысли. Intellij IDEA помогает быстро писать код с помощью live templates и code completion.

Live templates
Аббревиатуры для кода. Вводите 4 символа, нажимаете Enter, и они разворачиваются в 40.

Простые
St → String
sout
System.out.println();
main
public static void main(String[] args){}
prsf
private static final

Сложные
Разворачиваются в методы с параметрами для автозаполнения. Перемещаться между полями можно через Tab:

fori
for (int i=0; i< ; i++) {}
ifn
if (args == null) {}
mx
Math.max(, );
lazy
if (obj == null)
{ obj = new Integer(); }

Полный список live templates: File/Settings/Editor/Live Templates.

Есть для Java, Kotlin, JS, Groovy, для разработки под Android и React.

Code completion
Дополнение имен на основе контекста.

Начните набирать начало класса/метода:
Int → Integer
Cust → Customer

Для классов наберите заглавные буквы:
NPE → NullPointerException
CHM → ConcurrentHashMap

Добавьте синтаксическую конструкцию:
count == 4.if
if (count == 4) {}
list.for
for(Integer i : list) {}
obj.opt
Optional.of(obj)
answer.switch
switch (answer) {}

Полный список: File/Settings/Editor/General/Postfix Completion. Есть варианты для Java, Kotlin и JS.
1.5K views06:00
Открыть/Комментировать
2021-06-11 10:15:00 Generics, часть 2: вопросики

В этой части разберём wildcards, и как дженерики работают с иерархиями.

Начнём с ответа на вопрос перед постом. Компилятор выдаст ошибку.

Почему так?

Пойдём от обратного и представим, что метод принимает List>.

Внутри метода мы работаем со ссылкой на List>, значит в список можно добавить объект Parent. Если метод примет List>, значит List> тоже принимает объекты Parent. Что противоречит контракту, поэтому List> никак не связан с List>.

Здесь разработчики дженериков учли неудачный опыт с массивами. Для массивов возможна такая ситуация:
Создаём переменную arr с массивом Parent:
Parent[] arr;

Присваиваем массив Child:
arr = new Child[2];

Добавляем в arr экземпляры Child и Parent:
arr[0] = new Child();
arr[1] = new Parent();

Вторая строка в рантайме бросит ArrayStoreException. Дженерики обрабатываются при компиляции, поэтому ошибок на этапе выполнения нет.

Wildcards

Для ситуаций, когда мы точно-точно не будем менять список, и нам только посмотреть, можно использовать wildcards:

void print(List list)

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

Чем List отличается от List?

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

Как вызвать нужные методы для List>?

Тип в списке можно уточнить:

void print(List list)

Теперь метод принимает только List> и List>, плюс есть доступ к методам Parent. Но менять список всё ещё нельзя.

Буквы и вопросики

Есть два способа ограничить типы списков:

void test(List list)
void test(List list)

Чем они отличаются?

T - это конкретный тип элементов списка, поэтому в список можно добавить объекты типа Т. В листе с вопросиком конкретный тип НЕ известен, и компилятор НЕ даст добавить новые элементы.

extends и super

В иерархии Object - Parent - Child можно ограничить типы с разных сторон.

extends - ограничение иерархии "сверху"
? extends Parent: допустимы Parent, Child и наследники Child

super
- ограничение типов "снизу"
? super Parent принимает Parent и родителей Parent вплоть до Object
1.3K views07:15
Открыть/Комментировать