Java for Beginner
706 subscribers
614 photos
166 videos
12 files
958 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
📌 Факт дня:

А вы знали, что первая, крупнейшая в мире базой данных о кинематографе зародилась в 1990 году?

По состоянию на конец 2024 года, в Internet Movie Database (IMDb, в переводе с англ. — «Интернет-база фильмов») собрана информация о более чем 22 млн кинофильмов, телесериалов и отдельных их серий, а также о 14 млн персоналий, связанных с кино и телевидением, — актёрах, режиссёрах, сценаристах и других.

proof

#facts
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5
📌 Биография дня: Владимир Котельников

Владимир Котельников (1908–2005) — советский ученый, пионер теории связи. Его теорема об отсчетах легла в основу цифровой обработки сигналов, используемой в современных IT-системах, включая сжатие данных и телекоммуникации.


Биография

#Biography
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Задачи и жизненный цикл в Gradle


Task API: Task, DefaultTask, @TaskAction

Задачи (tasks) — это основная единица работы в Gradle, представляющая такие действия, как компиляция, тестирование или упаковка. Task API предоставляет инструменты для создания и настройки задач.


Основные компоненты

Task:
Интерфейс org.gradle.api.Task, определяющий базовую функциональность задачи (например, выполнение, зависимости).
Все задачи в Gradle реализуют этот интерфейс.


DefaultTask:
Класс org.gradle.api.DefaultTask, стандартная реализация интерфейса Task.
Используется для создания пользовательских задач.


Пример (Groovy DSL):
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction

class CustomTask extends DefaultTask {
@TaskAction
void executeTask() {
println 'Executing custom task'
}
}

tasks.register('customTask', CustomTask)


@TaskAction:
Аннотация, указывающая метод, который выполняется при запуске задачи.

Пример (Kotlin DSL):
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction

open class CustomTask : DefaultTask() {
@TaskAction
fun executeTask() {
println("Executing custom task")
}
}

tasks.register<CustomTask>("customTask")


В памяти: Каждая задача представлена как объект в JVM, содержащий метаданные (имя, зависимости, действия). Gradle загружает все задачи в память во время фазы конфигурации, что увеличивает потребление памяти пропорционально их количеству. Плагины, такие как java, добавляют множество задач (например, compileJava, test), увеличивая overhead.


Gradle Lifecycle

Жизненный цикл Gradle состоит из трех фаз: Initialization, Configuration и Execution. Каждая фаза выполняет определенные функции и влияет на производительность и память.

Initialization Phase:
Gradle загружает settings.gradle для определения структуры проекта (корневое имя, подмодули).
Создает объекты Project для корневого проекта и подпроектов.
Устанавливает начальные настройки, такие как репозитории и плагины.

В памяти: Минимальная фаза по потреблению ресурсов, так как загружается только settings.gradle и связанные плагины. Объем памяти зависит от количества модулей (обычно 50-100 МБ).


Configuration Phase:

Gradle парсит все файлы build.gradle, создавая модель проекта и граф задач (Directed Acyclic Graph, DAG).
Все скрипты конфигурации выполняются, даже для задач, которые не будут запущены.
Пример: Определение зависимостей, задач и плагинов.

В памяти: Самая ресурсоемкая фаза, так как Gradle загружает и компилирует все скрипты, плагины и зависимости. Для крупных проектов может потребоваться 500-1000 МБ памяти.

Оптимизация: Используйте флаг --configure-on-demand для конфигурации только необходимых модулей:
./gradlew build --configure-on-demand


Execution Phase:
Gradle выполняет задачи, указанные в командной строке (например, ./gradlew build), в порядке, определенном DAG.
Инкрементальность пропускает задачи, чьи входные/выходные данные не изменились (см. ниже).

В памяти: Зависит от сложности задач. Например, compileJava загружает исходные файлы и зависимости, а test — тестовые классы и фреймворки. Параллельное выполнение (--parallel) увеличивает пиковое потребление памяти.


Нюансы:

Конфигурация выполняется всегда, что замедляет сборку, особенно для крупных проектов.
Gradle Daemon сохраняет JVM между сборками, ускоряя повторные запуски, но увеличивая базовое потребление памяти (200-300 МБ).
Используйте --no-daemon для одноразовых сборок:

./gradlew build --no-daemon


#Java #middle #Gradle #Task #Lifecycle
👍1
Task Graph, зависимости между задачами

Gradle строит Directed Acyclic Graph (DAG) для задач, где узлы — задачи, а ребра — зависимости. Это определяет порядок выполнения.


Зависимости между задачами

dependsOn:
Указывает, что задача зависит от выполнения других задач.

Пример:
task compileJava {
doLast { println 'Compiling Java' }
}
task test(dependsOn: compileJava) {
doLast { println 'Running tests' }
}

Gradle выполнит compileJava перед test.


mustRunAfter:
Определяет порядок выполнения без строгой зависимости.

Пример:

task taskA {
doLast { println 'Task A' }
}
task taskB {
mustRunAfter 'taskA'
doLast { println 'Task B' }
}

Если обе задачи выполняются, taskB будет после taskA, но taskB может выполняться отдельно.


finalizedBy:
Указывает задачу, которая выполняется после завершения текущей, даже при ошибке.

Пример:
task build {
doLast { println 'Building' }
}
task cleanUp {
doLast { println 'Cleaning up' }
}
build.finalizedBy cleanUp


В памяти: DAG задач хранится как структура данных в JVM, где каждая задача — объект с метаданными (зависимости, действия). Размер графа пропорционален количеству задач, что может увеличить потребление памяти до нескольких сотен МБ в крупных проектах.



Incremental Build и Up-to-Date Checks

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

Механизм:
Gradle проверяет хэши входных (исходные файлы, свойства) и выходных данных (скомпилированные классы, JAR).
Если хэши совпадают, задача помечается как up-to-date и пропускается.


Пример вывода:
> Task :compileJava UP-TO-DATE


Пример настройки:
tasks.named('compileJava') {
inputs.files('src/main/java')
outputs.dir('build/classes/java/main')
}


В памяти: Gradle хранит хэши входов/выходов в памяти и в ~/.gradle/caches для сравнения. Это добавляет небольшой overhead (около 10-50 МБ), но значительно ускоряет сборку.


Нюансы:

Неправильная настройка входов/выходов может привести к ненужному выполнению задач.
Используйте --info для анализа, почему задача не была пропущена:

./gradlew build --info



Gradle Inputs/Outputs (Task Inputs/Outputs)

Задачи Gradle имеют входы и выходы, которые определяют, что влияет на выполнение задачи и что она производит.

Inputs:
Файлы, свойства или другие данные, от которых зависит задача.

Пример:
task processFiles {
inputs.files fileTree('src/main/resources')
doLast {
println 'Processing files'
}
}


Outputs:
Файлы или директории, создаваемые задачей.

Пример:
task generateReport {
outputs.file file('build/report.txt')
doLast {
file('build/report.txt').text = 'Report content'
}
}


В памяти: Gradle хранит метаданные входов/выходов в памяти и кэширует хэши в ~/.gradle/caches. Для задач с большим количеством файлов (например, compileJava) это увеличивает потребление памяти, так как Gradle сканирует файловую систему.


Нюансы:
Явно указывайте входы/выходы для кастомных задач, чтобы включить инкрементальность.

Используйте inputs.property для не-файловых входов:
task customTask {
inputs.property 'version', project.version
doLast { println "Version: ${project.version}" }
}



#Java #middle #Gradle #Task #Lifecycle
👍1
Do-first/do-last и ленивость (Provider, Property)

Gradle поддерживает гибкую настройку задач через doFirst и doLast, а также ленивую конфигурацию через Provider и Property.

doFirst и doLast:
doFirst: Добавляет действие в начало выполнения задачи.
doLast: Добавляет действие в конец выполнения задачи.


Пример:
task example {
doFirst { println 'Starting task' }
doLast { println 'Ending task' }
}


Ленивость (Provider, Property):
Gradle использует ленивую оценку для отсрочки вычислений до фазы выполнения.

Provider: Интерфейс для ленивых значений.def version = providers.provider { project.version }
task printVersion {
doLast {
println "Version: ${version.get()}"
}
}


Property: Для управления свойствами задачи.

task customTask {
def outputFile = objects.property(String)
outputFile.set('build/output.txt')
doLast {
println "Output: ${outputFile.get()}"
}
}


В памяти: doFirst и doLast добавляют действия как объекты в задачу, минимально увеличивая память. Ленивые Provider и Property хранят ссылки на значения, а не сами значения, что оптимизирует память до их вычисления в фазе выполнения.



Gradle Listeners и хуки

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

BuildListener:
Устаревший интерфейс для мониторинга событий сборки.

Пример:
gradle.buildFinished {
println 'Build completed'
}



TaskExecutionListener:

Отслеживает выполнение задач.

Пример:
gradle.taskGraph.whenReady {
println 'Task graph is ready'
}


Project.afterEvaluate:
Выполняется после фазы конфигурации.

Пример:
project.afterEvaluate {
println 'Project configured'
}

В памяти: Хуки создают дополнительные объекты-слушатели в памяти, увеличивая overhead. Для крупных проектов с множеством слушателей это может добавить 10-50 МБ памяти.


Нюансы:

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



Gradle Build Cache

Build Cache позволяет кэшировать результаты задач для повторного использования между сборками или машинами.

Настройка:
buildCache {
local {
enabled = true
}
remote(HttpBuildCache) {
url = 'https://cache.example.com/'
push = true
}
}


Как работает:
Gradle кэширует выходные данные задач (например, скомпилированные классы, JAR) в ~/.gradle/caches/build-cache или на удаленном сервере.
При повторной сборке Gradle проверяет хэши входов/выходов и использует кэшированные результаты, если они совпадают.
Пример: Задача compileJava кэширует классы в build/classes.


Использование:
Включите кэш:
./gradlew build --build-cache


Очистка локального кэша:
rm -rf ~/.gradle/caches/build-cache


В памяти: Build Cache требует хранения хэшей и метаданных в памяти во время выполнения, что добавляет 50-100 МБ overhead. Удаленный кэш увеличивает сетевые операции, но снижает локальные вычисления.


Нюансы:
Настройте входы/выходы задач точно, чтобы кэш работал корректно.
Build Cache наиболее эффективен для CI/CD, где результаты задач переиспользуются между сборками.



#Java #middle #Gradle #Task #Lifecycle
👍1
Что выведет код?

public class Task290725 {
public static void main(String[] args) {
Object lock1 = new Object();
Object lock2 = new Object();

new Thread(() -> {
synchronized(lock1) {
synchronized(lock2) {
System.out.println("Thread 1");
}
}
}).start();

new Thread(() -> {
synchronized(lock1) {
synchronized(lock2) {
System.out.println("Thread 2");
}
}
}).start();
}
}


#Tasks
👍1
Что такое IllegalArgumentException? 🤓

Ответ:

IllegalArgumentException — непроверяемое исключение, выбрасываемое при передаче недопустимых аргументов в метод.

Пример:
void setAge(int age) {
if (age < 0) throw new IllegalArgumentException("Age must be positive");
}

Используется для валидации входных данных.


#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍1