☕ Учебник по Java: введение в класс String
Оттачиваем навык работы со строчками: создание, форматирование, конкатенация строк и самые часто используемые методы.
https://proglib.io/sh/Va21eG9L4R
Зеркало: https://proglib.tech/p/uchebnik-po-java-vvedenie-v-klass-string-2022-08-26
Оттачиваем навык работы со строчками: создание, форматирование, конкатенация строк и самые часто используемые методы.
https://proglib.io/sh/Va21eG9L4R
Зеркало: https://proglib.tech/p/uchebnik-po-java-vvedenie-v-klass-string-2022-08-26
#вопросы_с_собеседований
Существует ли способ решения проблемы race condition?
Распространённые способы решения:
• Использование локальной копии — копирование разделяемой переменной в локальную переменную потока. Этот способ работает только тогда, когда переменная одна и копирование производится атомарно (за одну машинную команду), использование volatile.
• Синхронизация - операции над разделяемым ресурсом происходят в синхронизированном блоке (при использовании ключевого слова synchronized).
• Комбинирование методов - вышеперечисленные способы можно комбинировать, копируя «опасные» переменные в синхронизированном блоке. С одной стороны, это снимает ограничение на атомарность, с другой — позволяет избавиться от слишком больших синхронизированных блоков.
Очевидных способов выявления и исправления состояний гонки не существует. Лучший способ избавиться от гонок — правильное проектирование многозадачной системы.
Существует ли способ решения проблемы race condition?
Распространённые способы решения:
• Использование локальной копии — копирование разделяемой переменной в локальную переменную потока. Этот способ работает только тогда, когда переменная одна и копирование производится атомарно (за одну машинную команду), использование volatile.
• Синхронизация - операции над разделяемым ресурсом происходят в синхронизированном блоке (при использовании ключевого слова synchronized).
• Комбинирование методов - вышеперечисленные способы можно комбинировать, копируя «опасные» переменные в синхронизированном блоке. С одной стороны, это снимает ограничение на атомарность, с другой — позволяет избавиться от слишком больших синхронизированных блоков.
Очевидных способов выявления и исправления состояний гонки не существует. Лучший способ избавиться от гонок — правильное проектирование многозадачной системы.
Опрос «Библиотеки программиста»
Прошло почти полгода с момента нашего опроса «💬📈 Что сейчас происходит с IT-индустрией и айтишниками?». По версиям респондентов (более 700) IT-отрасль ждала волна сокращений, массовая релокация, наплыв стартапов и трудности с заменой железа и ПО на отечественные аналоги.
Общий прогноз звучал так: «Слишком много переменных, прогнозы от неутешительных до удовлетворительных»
Насколько оправдался этот прогноз? Как изменилась ваша жизнь за последние полгода?
➡️ Пройти опрос
Прошло почти полгода с момента нашего опроса «💬📈 Что сейчас происходит с IT-индустрией и айтишниками?». По версиям респондентов (более 700) IT-отрасль ждала волна сокращений, массовая релокация, наплыв стартапов и трудности с заменой железа и ПО на отечественные аналоги.
Общий прогноз звучал так: «Слишком много переменных, прогнозы от неутешительных до удовлетворительных»
Насколько оправдался этот прогноз? Как изменилась ваша жизнь за последние полгода?
➡️ Пройти опрос
Как написать свой первый автотест за 1 час?
Посетить открытое занятие курса "Автоматизация тестирования на Java" от ребят из школы автоматизации QA.GURU бесплатное открытое занятие состоится 7-го сентября в 20:00 МСК.
❓Почему надо сходить:
Для новичков:
— Разработаем ваш первый автотест на поиск в Google
—Расскажем о рынке QA. Кто, кому, за что и сколько платит?
— Дадим домашнее задание и проверим его у всех участников.
Для опытных:
— Расскажем про актуальный фреймворк на Java
— Покажем боевой проект с полной инфраструктурой (Web, API)
— Сессия вопросов и ответов с QA Lead
Занятие бесплатное — для участия вступайте в чат @qa_guru_chat — ссылка на занятие будет там.
Посетить открытое занятие курса "Автоматизация тестирования на Java" от ребят из школы автоматизации QA.GURU бесплатное открытое занятие состоится 7-го сентября в 20:00 МСК.
❓Почему надо сходить:
Для новичков:
— Разработаем ваш первый автотест на поиск в Google
—Расскажем о рынке QA. Кто, кому, за что и сколько платит?
— Дадим домашнее задание и проверим его у всех участников.
Для опытных:
— Расскажем про актуальный фреймворк на Java
— Покажем боевой проект с полной инфраструктурой (Web, API)
— Сессия вопросов и ответов с QA Lead
Занятие бесплатное — для участия вступайте в чат @qa_guru_chat — ссылка на занятие будет там.
#вопросы_с_собеседований
Как остановить поток?
На данный момент в Java принят уведомительный порядок остановки потока (хотя JDK 1.0 и имеет несколько управляющих выполнением потока методов, например stop(), suspend() и resume() - в следующих версиях JDK все они были помечены как deprecated из-за потенциальных угроз взаимной блокировки).
Для корректной остановки потока можно использовать метод класса Thread - interrupt(). Этот метод выставляет некоторый внутренний флаг-статус прерывания. В дальнейшем состояние этого флага можно проверить с помощью метода isInterrupted() или Thread.interrupted() (для текущего потока). Метод interrupt() также способен вывести поток из состояния ожидания или спячки. Т.е. если у потока были вызваны методы sleep() или wait() – текущее состояние прервется и будет выброшено исключение InterruptedException. Флаг в этом случае не выставляется.
Схема действия при этом получается следующей:
• Реализовать поток.
• В потоке периодически проводить проверку статуса прерывания через вызов isInterrupted().
• Если состояние флага изменилось или было выброшено исключение во время ожидания/спячки, следовательно поток пытаются остановить извне.
• Принять решение – продолжить работу (если по каким-то причинам остановиться невозможно) или освободить заблокированные потоком ресурсы и закончить выполнение.
Возможная проблема, которая присутствует в этом подходе – блокировки на потоковом вводе-выводе. Если поток заблокирован на чтении данных - вызов interrupt() из этого состояния его не выведет. Решения тут различаются в зависимости от типа источника данных. Если чтение идет из файла – долговременная блокировка крайне маловероятна и тогда можно просто дождаться выхода из метода read(). Если же чтение каким-то образом связано с сетью – стоит использовать неблокирующий ввод-вывод из Java NIO.
Второй вариант реализации метода остановки (а также и приостановки) – сделать собственный аналог interrupt(). Т.е. объявить в классе потока флаги – на остановку и/или приостановку и выставлять их путем вызова заранее определённых методов извне. Методика действия при этом остаётся прежней – проверять установку флагов и принимать решения при их изменении. Недостатки такого подхода. Во-первых, потоки в состоянии ожидания таким способом не «оживить». Во-вторых, выставление флага одним потоком совсем не означает, что второй поток тут же его увидит. Для увеличения производительности виртуальная машина использует кеш данных потока, в результате чего обновление переменной у второго потока может произойти через неопределенный промежуток времени (хотя допустимым решением будет объявить переменную-флаг как volatile).
Как остановить поток?
На данный момент в Java принят уведомительный порядок остановки потока (хотя JDK 1.0 и имеет несколько управляющих выполнением потока методов, например stop(), suspend() и resume() - в следующих версиях JDK все они были помечены как deprecated из-за потенциальных угроз взаимной блокировки).
Для корректной остановки потока можно использовать метод класса Thread - interrupt(). Этот метод выставляет некоторый внутренний флаг-статус прерывания. В дальнейшем состояние этого флага можно проверить с помощью метода isInterrupted() или Thread.interrupted() (для текущего потока). Метод interrupt() также способен вывести поток из состояния ожидания или спячки. Т.е. если у потока были вызваны методы sleep() или wait() – текущее состояние прервется и будет выброшено исключение InterruptedException. Флаг в этом случае не выставляется.
Схема действия при этом получается следующей:
• Реализовать поток.
• В потоке периодически проводить проверку статуса прерывания через вызов isInterrupted().
• Если состояние флага изменилось или было выброшено исключение во время ожидания/спячки, следовательно поток пытаются остановить извне.
• Принять решение – продолжить работу (если по каким-то причинам остановиться невозможно) или освободить заблокированные потоком ресурсы и закончить выполнение.
Возможная проблема, которая присутствует в этом подходе – блокировки на потоковом вводе-выводе. Если поток заблокирован на чтении данных - вызов interrupt() из этого состояния его не выведет. Решения тут различаются в зависимости от типа источника данных. Если чтение идет из файла – долговременная блокировка крайне маловероятна и тогда можно просто дождаться выхода из метода read(). Если же чтение каким-то образом связано с сетью – стоит использовать неблокирующий ввод-вывод из Java NIO.
Второй вариант реализации метода остановки (а также и приостановки) – сделать собственный аналог interrupt(). Т.е. объявить в классе потока флаги – на остановку и/или приостановку и выставлять их путем вызова заранее определённых методов извне. Методика действия при этом остаётся прежней – проверять установку флагов и принимать решения при их изменении. Недостатки такого подхода. Во-первых, потоки в состоянии ожидания таким способом не «оживить». Во-вторых, выставление флага одним потоком совсем не означает, что второй поток тут же его увидит. Для увеличения производительности виртуальная машина использует кеш данных потока, в результате чего обновление переменной у второго потока может произойти через неопределенный промежуток времени (хотя допустимым решением будет объявить переменную-флаг как volatile).
#вопросы_с_собеседований
Что происходит, когда в потоке выбрасывается исключение?
• Если исключение не поймано – поток «умирает» (переходит в состяние мёртв (
• Если установлен обработчик непойманных исключений, то он возьмёт управление на себя.
Что происходит, когда в потоке выбрасывается исключение?
• Если исключение не поймано – поток «умирает» (переходит в состяние мёртв (
dead
)).• Если установлен обработчик непойманных исключений, то он возьмёт управление на себя.
Thread.UncaughtExceptionHandler
– интерфейс, определённый как вложенный интерфейс для других обработчиков, вызываемых, когда поток внезапно останавливается из-за непойманного исключения. В случае, если поток собирается остановиться из-за непойманного исключения, JVM
проверяет его на наличие UncaughtExceptionHandler
, используя Thread.getUncaughtExceptionHandler()
, и если такой обработчик найдет, то вызовет у него метод uncaughtException()
, передав этот поток и исключение в виде аргументов.#вопросы_с_собеседований
В чем разница между interrupted() и isInterrupted()?
Механизм прерывания работы потока в
Когда прерванный поток проверяет статус прерывания, вызывая статический метод
Нестатический метод
В чем разница между interrupted() и isInterrupted()?
Механизм прерывания работы потока в
Java
реализован с использованием внутреннего флага, известного как статус прерывания. Прерывание потока вызовом Thread.interrupt()
устанавливает этот флаг. Методы Thread.interrupted()
и isInterrupted()
позволяют проверить, является ли поток прерванным.Когда прерванный поток проверяет статус прерывания, вызывая статический метод
Thread.interrupted()
, статус прерывания сбрасывается.Нестатический метод
isInterrupted()
используется одним потоком для проверки статуса прерывания у другого потока, не изменяя флаг прерывания.Кастомный отчет для Jira или как приключение затянулось.
https://habr.com/ru/company/nlmk/blog/681874/
https://habr.com/ru/company/nlmk/blog/681874/
Хабр
Кастомный отчет для Jira или как приключение затянулось
Представим ситуацию – вам надо сделать небольшой отчет на основе данных из другой системы. Звучит обыденно и вы сразу в голове представляете, что надо будет делать: узнать какие будут входные данные и...
⚒ Зачем использовать функциональное программирование, если есть ООП?
Легко писать, легко отлаживать и использовать повторно. Правда ли это? Давайте разбираться.
https://proglib.io/sh/ygPOrh7i8C
Легко писать, легко отлаживать и использовать повторно. Правда ли это? Давайте разбираться.
https://proglib.io/sh/ygPOrh7i8C
Примитивы, врапперы. Package/unpackage (boxing/unboxing).
• Типы-примитивы не создаются в куче, их жизненный цикл ограничен жизненным циклом стек-фрейма
• Package — создание типа-обертки в хипе для аналогичного типа-примитива, например при объявлении аргумента как Integer, и при передаче int в качестве аргумента. Unpackage — обратная операция
• Типы-примитивы не создаются в куче, их жизненный цикл ограничен жизненным циклом стек-фрейма
• Package — создание типа-обертки в хипе для аналогичного типа-примитива, например при объявлении аргумента как Integer, и при передаче int в качестве аргумента. Unpackage — обратная операция
#вопросы_с_собеседований
Что такое «пул потоков»?
Создание потока является затратной по времени и ресурсам операцией. Количество потоков, которое может быть запущено в рамках одного процесса также ограниченно. Чтобы избежать этих проблем и в целом управлять множеством потоков более эффективно в
Начиная с
•
•
•
•
•
•
... и другие.
Методы
•
•
•
•
•
•
•
•
•
Что такое «пул потоков»?
Создание потока является затратной по времени и ресурсам операцией. Количество потоков, которое может быть запущено в рамках одного процесса также ограниченно. Чтобы избежать этих проблем и в целом управлять множеством потоков более эффективно в
Java
был реализован механизм пула потоков (thread pool
), который создаётся во время запуска приложения и в дальнейшем потоки для обработки запросов берутся и переиспользуются уже из него. Таким образом, появляется возможность не терять потоки, сбалансировать приложение по количеству потоков и частоте их создания.Начиная с
Java 1.5 Java API
предоставляет фреймворк Executor
, который позволяет создавать различные типы пула потоков:•
Executor
- упрощенный интерфейс пула, содержит один метод для передачи задачи на выполнение;•
ExecutorService
- расширенный интерфейс пула, с возможностью завершения всех потоков;•
AbstractExecutorService
- базовый класс пула, реализующий интерфейс ExecutorService
;•
Executors
- фабрика объектов связанных с пулом потоков, в том числе позволяет создать основные типы пулов;•
ThreadPoolExecutor
- пул потоков с гибкой настройкой, может служить базовым классом для нестандартных пулов;•
ForkJoinPool
- пул для выполнения задач типа ForkJoinTask;... и другие.
Методы
Executors
для создания пулов:•
newCachedThreadPool()
- если есть свободный поток, то задача выполняется в нем, иначе добавляется новый поток в пул. Потоки не используемые больше минуты завершаются и удалются и кэша. Размер пула неограничен. Предназначен для выполнения множество небольших асинхронных задач;•
newCachedThreadPool(ThreadFactory threadFactory)
- аналогично предыдущему, но с собственной фабрикой потоков;•
newFixedThreadPool(int nThreads)
- создает пул на указанное число потоков. Если новые задачи добавлены, когда все потоки активны, то они будут сохранены в очереди для выполнения позже. Если один из потоков завершился из-за ошибки, на его место будет запущен другой поток. Потоки живут до тех пор, пока пул не будет закрыт явно методом shutdown()
.•
newFixedThreadPool(int nThreads, ThreadFactory threadFactory)
- аналогично предыдущему, но с собственной фабрикой потоков;•
newSingleThreadScheduledExecutor()
- однопотоковый пул с возможностью выполнять задачу через указанное время или выполнять периодически. Если поток был завершен из-за каких-либо ошибок, то для выполнения следующей задачи будет создан новый поток.•
newSingleThreadScheduledExecutor(ThreadFactory threadFactory)
- аналогично предыдущему, но с собственной фабрикой потоков;•
newScheduledThreadPool(int corePoolSize)
- пул для выполнения задач через указанное время или переодически;•
newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)
- аналогично предыдущему, но с собственной фабрикой потоков;•
unconfigurableExecutorService(ExecutorService executor)
- обертка на пул, запрещающая изменять его конфигурацию;#вопросы_с_собеседований
Какого размера должен быть пул потоков?
Настраивая размер пула потоков, важно избежать двух ошибок: слишком мало потоков (очередь на выполнение будет расти, потребляя много памяти) или слишком много потоков (замедление работы всей систему из-за частых переключений контекста).
Оптимальный размер пула потоков зависит от количества доступных процессоров и природы задач в рабочей очереди. На
Использование процессора – не единственный фактор, важный при настройке размера пула потоков. По мере возрастания пула потоков, можно столкнуться с ограничениями планировщика, доступной памяти, или других системных ресурсов, таких, как количество сокетов, дескрипторы открытого файла, или каналы связи базы данных.
Какого размера должен быть пул потоков?
Настраивая размер пула потоков, важно избежать двух ошибок: слишком мало потоков (очередь на выполнение будет расти, потребляя много памяти) или слишком много потоков (замедление работы всей систему из-за частых переключений контекста).
Оптимальный размер пула потоков зависит от количества доступных процессоров и природы задач в рабочей очереди. На
N-процессорной
системе для рабочей очереди, которая будет выполнять исключительно задачи с ограничением по скорости вычислений, можно достигнуть максимального использования CPU
с пулом потоков, в котором содержится N
или N+1
поток. Для задач, которые могут ждать осуществления I/O
(ввода - вывода) - например, задачи, считывающей HTTP-запрос
из сокета – может понадобиться увеличение размера пула свыше количества доступных процессоров, потому, что не все потоки будут работать все время. Используя профилирование, можно оценить отношение времени ожидания (WT
) ко времени обработки (ST
) для типичного запроса. Если назвать это соотношение WT/ST
, то для N-процессорной
системе понадобится примерно N*(1 + WT/ST)
потоков для полной загруженности процессоров.Использование процессора – не единственный фактор, важный при настройке размера пула потоков. По мере возрастания пула потоков, можно столкнуться с ограничениями планировщика, доступной памяти, или других системных ресурсов, таких, как количество сокетов, дескрипторы открытого файла, или каналы связи базы данных.
Что будет, если очередь пула потоков уже заполнена, но подаётся новая задача?
Если очередь пула потоков заполнилась, то поданная задача будет «отклонена». Например - метод submit() у ThreadPoolExecutor выкидывает RejectedExecutionException, после которого вызывается RejectedExecutionHandler.
Если очередь пула потоков заполнилась, то поданная задача будет «отклонена». Например - метод submit() у ThreadPoolExecutor выкидывает RejectedExecutionException, после которого вызывается RejectedExecutionHandler.
«Библиотека программиста» находится в поиске авторов оригинальных статей
Языки:
– Python, JavaScript, TypeScript, Java, C#, Go, SQL.
Тематики:
– Информационная безопасность, Data Science, базовые концепции языков, продвинутый Python, JS (и т. д), бэкенд веб-приложений, фронтенд-разработка, React, системное программирование, базы данных.
Объем:
– от 7 до 15 тыс. знаков.
➡️ Заполнить анкету ⬅️
Я хорошо программирую, но пишу «так себе». Что делать?
Если вы хорошо программируете, но навыки письма немного отстают, пройдите наш бесплатный курс на Степике «Статьи для IT: как объяснять и распространять значимые идеи».
Языки:
– Python, JavaScript, TypeScript, Java, C#, Go, SQL.
Тематики:
– Информационная безопасность, Data Science, базовые концепции языков, продвинутый Python, JS (и т. д), бэкенд веб-приложений, фронтенд-разработка, React, системное программирование, базы данных.
Объем:
– от 7 до 15 тыс. знаков.
➡️ Заполнить анкету ⬅️
Я хорошо программирую, но пишу «так себе». Что делать?
Если вы хорошо программируете, но навыки письма немного отстают, пройдите наш бесплатный курс на Степике «Статьи для IT: как объяснять и распространять значимые идеи».
В чём заключается различие между методами submit() и execute() у пула потоков?
Оба метода являются способами подачи задачи в пул потоков, но между ними есть небольшая разница.
execute(Runnable command) определён в интерфейсе Executor и выполняет поданную задачу и ничего не возвращает.
submit() – перегруженный метод, определённый в интерфейсе ExecutorService. Способен принимать задачи типов Runnable и Callable и возвращать объект Future, который можно использовать для контроля и управления процессом выполнения, получения его результата.
Оба метода являются способами подачи задачи в пул потоков, но между ними есть небольшая разница.
execute(Runnable command) определён в интерфейсе Executor и выполняет поданную задачу и ничего не возвращает.
submit() – перегруженный метод, определённый в интерфейсе ExecutorService. Способен принимать задачи типов Runnable и Callable и возвращать объект Future, который можно использовать для контроля и управления процессом выполнения, получения его результата.
#вопросы_с_собеседований
Для чего нужны функциональные интерфейсы вида _To_Function?
DoubleToIntFunction - операция, принимающая аргумент класса Double и возвращающая результат типа Integer;
DoubleToLongFunction - операция, принимающая аргумент класса Double и возвращающая результат типа Long;
IntToDoubleFunction - операция, принимающая аргумент класса Integer и возвращающая результат типа Double;
IntToLongFunction - операция, принимающая аргумент класса Integer и возвращающая результат типа Long;
LongToDoubleFunction - операция, принимающая аргумент класса Long и возвращающая результат типа Double;
LongToIntFunction - операция, принимающая аргумент класса Long и возвращающая результат типа Integer.
Для чего нужны функциональные интерфейсы вида _To_Function?
DoubleToIntFunction - операция, принимающая аргумент класса Double и возвращающая результат типа Integer;
DoubleToLongFunction - операция, принимающая аргумент класса Double и возвращающая результат типа Long;
IntToDoubleFunction - операция, принимающая аргумент класса Integer и возвращающая результат типа Double;
IntToLongFunction - операция, принимающая аргумент класса Integer и возвращающая результат типа Long;
LongToDoubleFunction - операция, принимающая аргумент класса Long и возвращающая результат типа Double;
LongToIntFunction - операция, принимающая аргумент класса Long и возвращающая результат типа Integer.