Что такое livelock?
Реальный пример
👉@BookJava
livelock
– тип взаимной блокировки, при котором несколько потоков выполняют бесполезную работу, попадая в зацикленность при попытке получения каких-либо ресурсов. При этом их состояния постоянно изменяются в зависимости друг от друга. Фактической ошибки не возникает, но КПД системы падает до 0. Часто возникает в результате попыток предотвращения deadlock.Реальный пример
livelock
, – когда два человека встречаются в узком коридоре и каждый, пытаясь быть вежливым, отходит в сторону, и так они бесконечно двигаются из стороны в сторону, абсолютно не продвигаясь в нужном им направлении.👉@BookJava
👍8
Java 20: огромные разреженные сегменты памяти
Знаете ли вы, что можно выделять сегменты памяти, которые больше, чем физический размер оперативной памяти вашего компьютера, и даже больше, чем размер всей вашей файловой системы? Прочтите эту статью и узнайте, как использовать сопоставленные (mapped) сегменты памяти, которые могут быть или не быть «разреженными», и как выделить 64 терабайта разреженных данных на ноутбуке.
Rus https://habr.com/ru/post/710664/
Eng https://minborgsjavapot.blogspot.com/2023/01/java-20-colossal-sparse-memory-segments.html
👉@BookJava
Знаете ли вы, что можно выделять сегменты памяти, которые больше, чем физический размер оперативной памяти вашего компьютера, и даже больше, чем размер всей вашей файловой системы? Прочтите эту статью и узнайте, как использовать сопоставленные (mapped) сегменты памяти, которые могут быть или не быть «разреженными», и как выделить 64 терабайта разреженных данных на ноутбуке.
Rus https://habr.com/ru/post/710664/
Eng https://minborgsjavapot.blogspot.com/2023/01/java-20-colossal-sparse-memory-segments.html
👉@BookJava
В чём различия между volatile и Atomic переменными?
👉@BookJava
volatile
принуждает использовать единственный экземпляр переменной, но не гарантирует атомарность. Например, операция count++ не станет атомарной просто потому, что count объявлена volatile
. C другой стороны class AtomicInteger
предоставляет атомарный метод для выполнения таких комплексных операций атомарно, например getAndIncrement()
– атомарная замена оператора инкремента, его можно использовать, чтобы атомарно увеличить текущее значение на один. Похожим образом сконструированы атомарные версии и для других типов данных.👉@BookJava
👍4
Чем отличаются JRE, JVM И JDK?
JRE кратко - для работы. Java Runtime Environment (сокр. JRE) - минимальная реализация виртуальной машины, необходимая для исполнения Java-приложений, без компилятора и других средств разработки. Состоит из виртуальной машины - Java Virtual Machine и библиотеки Java-классов.
JDK кратко - для программирования. Java Development Kit (сокращенно JDK) - бесплатно распространяемый компанией Oracle Corporation (ранее Sun Microsystems) комплект разработчика приложений на языке Java, включающий в себя компилятор Java (javac), стандартные библиотеки классов Java, примеры, документацию, различные утилиты и исполнительную систему Java (JRE).
Java Virtual Machine (сокращенно Java VM, JVM) - виртуальная машина Java - основная часть исполняющей системы Java, так называемой Java Runtime Environment (JRE). Виртуальная машина Java интерпретирует Байт-код Java, предварительно созданный из исходного текста Java-программы компилятором Java (javac). JVM может также использоваться для выполнения программ, написанных на других языках программирования.
👉@BookJava
JRE кратко - для работы. Java Runtime Environment (сокр. JRE) - минимальная реализация виртуальной машины, необходимая для исполнения Java-приложений, без компилятора и других средств разработки. Состоит из виртуальной машины - Java Virtual Machine и библиотеки Java-классов.
JDK кратко - для программирования. Java Development Kit (сокращенно JDK) - бесплатно распространяемый компанией Oracle Corporation (ранее Sun Microsystems) комплект разработчика приложений на языке Java, включающий в себя компилятор Java (javac), стандартные библиотеки классов Java, примеры, документацию, различные утилиты и исполнительную систему Java (JRE).
Java Virtual Machine (сокращенно Java VM, JVM) - виртуальная машина Java - основная часть исполняющей системы Java, так называемой Java Runtime Environment (JRE). Виртуальная машина Java интерпретирует Байт-код Java, предварительно созданный из исходного текста Java-программы компилятором Java (javac). JVM может также использоваться для выполнения программ, написанных на других языках программирования.
👉@BookJava
👍5
Отличие интерфейса Runnable и Callable?
• Интерфейс Runnable появился в Java 1.0, а интерфейс Callable был введен в Java 5.0 в составе библиотеки
• Классы, реализующие интерфейс
• Метод
•
👉@BookJava
• Интерфейс Runnable появился в Java 1.0, а интерфейс Callable был введен в Java 5.0 в составе библиотеки
java.util.concurrent
;• Классы, реализующие интерфейс
Runnable
для выполнения задачи должны реализовывать метод run()
. Классы, реализующие интерфейс Callable
- метод call()
;• Метод
Runnable.run()
не возвращает никакого значения, Callable.call()
возвращает объект Future
, который может содержать результат вычислений;•
Метод run()
не может выбрасывать проверяемые исключения, в то время как метод call()
может.👉@BookJava
👍5
💩3👍2🔥1
Как остановить поток?
На данный момент в Java принят уведомительный порядок остановки потока (хотя JDK 1.0 и имеет несколько управляющих выполнением потока методов, например
Для корректной остановки потока можно использовать метод класса Thread - interrupt(). Этот метод выставляет некоторый внутренний флаг-статус прерывания. В дальнейшем состояние этого флага можно проверить с помощью метода
Схема действия при этом получается следующей:
• Реализовать поток.
• В потоке периодически проводить проверку статуса прерывания через вызов
• Если состояние флага изменилось или было выброшено исключение во время ожидания/спячки, следовательно поток пытаются остановить извне.
• Принять решение – продолжить работу (если по каким-то причинам остановиться невозможно) или освободить заблокированные потоком ресурсы и закончить выполнение.
Возможная проблема, которая присутствует в этом подходе – блокировки на потоковом вводе-выводе. Если поток заблокирован на чтении данных - вызов interrupt() из этого состояния его не выведет. Решения тут различаются в зависимости от типа источника данных. Если чтение идет из файла – долговременная блокировка крайне маловероятна и тогда можно просто дождаться выхода из метода read(). Если же чтение каким-то образом связано с сетью – стоит использовать неблокирующий ввод-вывод из Java NIO.
Второй вариант реализации метода остановки (а также и приостановки) – сделать собственный аналог
👉@BookJava
На данный момент в 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).👉@BookJava
👍1
Какого размера должен быть пул потоков?
Настраивая размер пула потоков, важно избежать двух ошибок: слишком мало потоков (очередь на выполнение будет расти, потребляя много памяти) или слишком много потоков (замедление работы всей систему из-за частых переключений контекста).
Оптимальный размер пула потоков зависит от количества доступных процессоров и природы задач в рабочей очереди. На N-процессорной системе для рабочей очереди, которая будет выполнять исключительно задачи с ограничением по скорости вычислений, можно достигнуть максимального использования CPU с пулом потоков, в котором содержится N или N+1 поток. Для задач, которые могут ждать осуществления I/O (ввода - вывода) - например, задачи, считывающей HTTP-запрос из сокета – может понадобиться увеличение размера пула свыше количества доступных процессоров, потому, что не все потоки будут работать все время. Используя профилирование, можно оценить отношение времени ожидания (WT) ко времени обработки (ST) для типичного запроса. Если назвать это соотношение WT/ST, то для N-процессорной системе понадобится примерно N*(1 + WT/ST) потоков для полной загруженности процессоров.
Использование процессора – не единственный фактор, важный при настройке размера пула потоков. По мере возрастания пула потоков, можно столкнуться с ограничениями планировщика, доступной памяти, или других системных ресурсов, таких, как количество сокетов, дескрипторы открытого файла, или каналы связи базы данных.
👉@BookJava
Настраивая размер пула потоков, важно избежать двух ошибок: слишком мало потоков (очередь на выполнение будет расти, потребляя много памяти) или слишком много потоков (замедление работы всей систему из-за частых переключений контекста).
Оптимальный размер пула потоков зависит от количества доступных процессоров и природы задач в рабочей очереди. На N-процессорной системе для рабочей очереди, которая будет выполнять исключительно задачи с ограничением по скорости вычислений, можно достигнуть максимального использования CPU с пулом потоков, в котором содержится N или N+1 поток. Для задач, которые могут ждать осуществления I/O (ввода - вывода) - например, задачи, считывающей HTTP-запрос из сокета – может понадобиться увеличение размера пула свыше количества доступных процессоров, потому, что не все потоки будут работать все время. Используя профилирование, можно оценить отношение времени ожидания (WT) ко времени обработки (ST) для типичного запроса. Если назвать это соотношение WT/ST, то для N-процессорной системе понадобится примерно N*(1 + WT/ST) потоков для полной загруженности процессоров.
Использование процессора – не единственный фактор, важный при настройке размера пула потоков. По мере возрастания пула потоков, можно столкнуться с ограничениями планировщика, доступной памяти, или других системных ресурсов, таких, как количество сокетов, дескрипторы открытого файла, или каналы связи базы данных.
👉@BookJava
❤🔥1👍1
Arrays.fill in Java
Вы когда-нибудь думали, как заполнить весь массив одним и тем же значением в Java?
В CPP мы используем memset или можем инициализировать любое значение, когда дело доходит до java, мы используем Arrays.Fill().
https://dev.to/swapnilxi/arraysfill-in-java-2mk5
👉@BookJava
Вы когда-нибудь думали, как заполнить весь массив одним и тем же значением в Java?
В CPP мы используем memset или можем инициализировать любое значение, когда дело доходит до java, мы используем Arrays.Fill().
https://dev.to/swapnilxi/arraysfill-in-java-2mk5
👉@BookJava
DEV Community
Arrays.fill in Java
Ever thought how to fill the whole array with same value in Java !? in CPP, we use memset or can...
👍2
👍1
В чём заключается различие между методами submit() и execute() у пула потоков?
Оба метода являются способами подачи задачи в пул потоков, но между ними есть небольшая разница.
👉@BookJava
Оба метода являются способами подачи задачи в пул потоков, но между ними есть небольшая разница.
execute(Runnable command)
определён в интерфейсе Executor
и выполняет поданную задачу и ничего не возвращает.submit()
– перегруженный метод, определённый в интерфейсе ExecutorService
. Способен принимать задачи типов Runnable
и Callable
и возвращать объект Future
, который можно использовать для контроля и управления процессом выполнения, получения его результата.👉@BookJava
Какие значения возвращают мутаторы Map?
Давайте разберемся с этой путаницей раз и навсегда.
• Методы put (
• Методы работы с множеством элементов (
•
• Методы с коллбэками (
👉@BookJava
Давайте разберемся с этой путаницей раз и навсегда.
• Методы put (
put
, putIfAbsent
) возвращают старое значение.• Методы работы с множеством элементов (
putAll
, replaceAll
, clear
) не возвращают ничего.•
remove
и replace
с указанием не только ключа, но и старого значения, возвращают boolean
; без указания – это самое старое значение.• Методы с коллбэками (
computeIfPresent
, computeIfAbsent
, compute, merge
) возвращают актуальное значение после вызова, оставшееся или новое.👉@BookJava
👍2