MiddlePython Developer > Основы Python > Многопоточность и асинхронность
Короткий ответ Модуль threading предоставляет класс Thread: поток создаётся вокруг callable-объекта, запускается методом start() и ожидается через join(). Из-за GIL в каждый момент исполняется один поток, поэтому многопоточность эффективна прежде всего для задач ввода-вывода. Как это работает подробнее Потоками управляет операционная система, но CPython через GIL ограничивает одновременное исполнение Python-байткода одним потоком. Глобальная блокировка. Для CPU-bound задач потоки не дают ускорения: остальные потоки ждут освобождения GIL. Ожидание ввода-вывода. Пока поток ждёт ответа от сети, диска или базы данных, GIL свободен, и другие потоки выполняют код. Синхронизация. При изменении общих данных возникают состояния гонки, поэтому используют блокировки Lock и семафоры Semaphore. Безопасная передача данных. Для обмена данными между потоками удобно использовать queue.Queue. Настоящий параллелизм. Чтобы задействовать несколько ядер процессора, применяют multiprocessing или библиотеки вроде joblib, запускающие
concurrencygil
JuniorJava Developer > Java Core > Collections
Короткий ответ Несмотря на похожие названия, это разные сущности. java.util.Collection — это интерфейс, корень иерархии коллекций: от него наследуются List, Set и Queue, а сам он задаёт базовый контракт — size(), isEmpty(), add(E), remove(Object), contains(Object), iterator(). java.util.Collections — это утилитный класс со статическими методами для работы с коллекциями. Как это работает подробнее Создать «объект Collection» напрямую нельзя: интерфейс можно лишь реализовать или использовать одного из наследников. Класс Collections не участвует в иерархии коллекций и содержит только готовые алгоритмы и обёртки. Алгоритмы: сортировка sort, перемешивание shuffle, реверс reverse, бинарный поиск binarySearch, поиск максимума и минимума. Обёртки: неизменяемые представления unmodifiableList, unmodifiableMap и синхронизированные synchronizedList, synchronizedMap. Создание: пустые коллекции через emptyList(), коллекция из одного элемента — через singletonList(). Пример кода Что использовать на практике В полях и сигнат
collectionsinterface
SeniorJava Developer > Java Core > Сборка мусора
Короткий ответ В HotSpot JVM исторически сменяли друг друга несколько сборщиков: Serial GC (-XX:+UseSerialGC), Parallel GC, он же Throughput Collector (-XX:+UseParallelGC), CMS (Concurrent Mark Sweep), затем G1 (-XX:+UseG1GC), ставший сборщиком по умолчанию с Java 9, и ZGC для сверхнизких пауз. Все они останавливают приложение на время сборки (stop-the-world), но современные выполняют основную работу конкурентно. Как это работает подробнее Serial GC — самый простой: сборка выполняется одним потоком, подходит для небольших приложений с маленькой кучей и одним-двумя ядрами. Parallel GC (Throughput Collector) — сборщик по умолчанию до Java 8: молодое и старое поколения чистит несколькими рабочими потоками, давая максимальную пропускную способность, но его паузы могут быть заметными. CMS выполнял большую часть пометки параллельно с работающим приложением ради уменьшения пауз, но не уплотнял кучу (отсюда фрагментация) и был помечен устаревшим в JDK 9, а позже удалён. G1 (Garbage First) делит кучу на регионы одинак
cmsg1
MiddleJava Developer > Java Core > Spring
Короткий ответ Autowiring — механизм автоматического связывания бинов, который выполняет контейнер Spring, обычно по аннотации @Autowired; он избавляет от ручной настройки связей и способствует слабой связанности. Выделяют три способа внедрения: через конструктор, через сеттер и напрямую в поле класса. Как это работает подробнее Рекомендуемый подход — конструкторная инъекция, особенно для обязательных зависимостей: объект создаётся полностью инициализированным, зависимости нельзя поменять после создания, исключается частично инициализированное состояние и связанные с ним ошибки, а класс легко тестировать, передавая моки в конструктор. Сеттерная инъекция уместна для опциональных зависимостей, которые могут меняться в процессе жизни объекта. Инъекция в поле через @Autowired проста в написании, но скрывает зависимости, мешает тестированию (сложно подставить мок без контейнера) и нарушает неизменяемость. Важный нюанс: если у бина один конструктор, явная @Autowired на нём не обязательна — контейнер использует его
autowiredconstructor-injection
JuniorJava Developer > Java Core > Основы Java
Короткий ответ Значения по умолчанию присваиваются полям класса (переменным экземпляра и статическим переменным), если им явно ничего не присвоено. Числовые примитивы получают ноль в своём виде, char — нулевой символ, boolean — false, ссылочные поля (включая String) — null. Локальные переменные исключение: значений по умолчанию у них нет. Как это работает подробнее JVM инициализирует поля в момент создания объекта или загрузки класса — ещё до вызова конструктора. То же правило действует для элементов массива: при его создании все ячейки заполняются значениями по умолчанию. Числа: byte, short, int → 0; long → 0L; float → 0.0f; double → 0.0d. Символы и логика: char → нулевой символ; boolean → false. Ссылки: любые поля объектных типов (включая String) → null, то есть ссылка «ни на что». Локальные переменные внутри метода не инициализируются автоматически: обращение до присваивания — ошибка компиляции. Пример кода Что использовать на практике Локальные переменные инициализировать до использования — иначе код не с
default-valuesjava
MiddleJava Developer > Java Core > Spring
Короткий ответ Область видимости (scope) определяет, сколько экземпляров бина создаёт контейнер и как они используются. По умолчанию все бины — singleton: один экземпляр на весь контейнер. Скоуп prototype создаёт новый экземпляр при каждом запросе из контейнера. Как это работает подробнее Spring поддерживает шесть скоупов: singleton (один экземпляр на весь контейнер), prototype (новый экземпляр на каждый запрос), request (на каждый HTTP-запрос), session (на каждую HTTP-сессию), application (общий для всего веб-приложения) и websocket (на каждую WebSocket-сессию). Скоупы request, session, application и websocket доступны только в веб-приложениях. Singleton: контейнер создаёт один экземпляр и полностью управляет его жизненным циклом, включая вызов метода уничтожения при завершении приложения; экономит память и подходит для stateless-бинов — сервисов и репозиториев. Prototype: при каждом запросе создаётся новый объект; после передачи вызывающему коду контейнер больше не управляет им, поэтому метод уничтожения дл
bean-scopejava
MiddleJava Developer > Java Core > Collections
Короткий ответ Главное отличие — потокобезопасность: у Hashtable синхронизированы все методы, и из-за глобальной синхронизации на каждый вызов она медленнее; HashMap не синхронизирован и безопасен только для одного потока. Второе важное отличие — работа с null: HashMap допускает один null-ключ и любое количество null-значений, а Hashtable выбрасывает NullPointerException на ключ или значение null. Как это работает подробнее В HashMap для null предусмотрен специальный путь: такой ключ попадает в корзину с индексом 0 без вызова hashCode, поэтому null разрешён; дизайн Hashtable такой поддержки не предполагает. Наследования между классами нет: HashMap унаследован от AbstractMap, а Hashtable — от Dictionary, это разные ветви иерархии. Итераторы и HashMap, и Hashtable являются fail-fast. Современная замена: ConcurrentHashMap даёт более высокую конкурентность за счёт сегментации, а в Java 8+ — CAS-операций с точечной синхронизацией отдельных корзин. Общее: и Hashtable, и ConcurrentHashMap не допускают null-ключи и n
collectionsconcurrent
MiddleJava Developer > Java Core > JPA и Hibernate
Короткий ответ В Hibernate сущность проходит четыре состояния. Transient — объект только что создан через new, не связан с Session и не имеет соответствия в базе. Persistent — связан с открытой Session и имеет запись в БД, изменения отслеживаются. Detached — был persistent, но Session закрыта или вызваны evict()/detach(). Removed — помечен на удаление и будет удалён при синхронизации. Как это работает подробнее Переходы выполняются операциями Session: save()/persist() переводят transient в persistent, закрытие сессии или evict() — в detached, а update(), saveOrUpdate() или merge() возвращают объект в persistent. От состояния зависит, какие операции Hibernate выполнит при коммите и какие исключения могут возникнуть. Transient: объект не управляется Hibernate, записи в базе ещё нет. Persistent: работает dirty checking — Hibernate сам синхронизирует изменения с БД при flush или commit, явный update() не нужен. Detached: изменения больше не отслеживаются; чтобы сохранить их, объект нужно присоединить заново. Remo
detachedentity-lifecycle
MiddlePython Developer > Основы Python > Инструменты разработки
Короткий ответ Простейший способ — временно выводить значения через print(), для системной диагностики удобнее логирование модулем logging. Настоящий отладчик Python — модуль pdb: он даёт точки останова, пошаговое выполнение, просмотр стека и вычисление выражений. С Python 3.7 его запускает встроенная функция breakpoint(). Как это работает подробнее Методы отладки отличаются глубиной: печать помогает быстро, но для сложных ошибок нужен полноценный интерактивный отладчик. Печать. Временный print() значений переменных — самый простой способ быстрой проверки. Логирование. Модуль logging записывает данные о работе программы и позволяет настраивать уровень и формат сообщений. Отладчик pdb. Поддерживает условные точки останова и пошаговое выполнение по строкам исходного кода, просмотр кадров стека и вычисление произвольных выражений в контексте любого кадра. Запуск. Классический приём — import pdb; pdb.set_trace(), современный — встроенная функция breakpoint(), после остановки выполнение продолжают командой continu
breakpointsdebugging
JuniorJava Developer > Java Core > Multithreading
Короткий ответ Первый способ — создать подкласс Thread и переопределить метод run(). Второй — реализовать интерфейс Runnable и передать экземпляр задания в конструктор Thread. Запускает поток всегда метод start(): именно он создаёт новый поток и внутри него вызывает run(). Как это работает подробнее Наследование от Thread смешивает задачу («что делать») с потоком («где выполнять») и расходует единственное место под наследование. Реализация Runnable считается предпочтительной: Java поддерживает только одиночное наследование, а интерфейс такой проблемы не создаёт; один и тот же объект Runnable можно передать в несколько потоков или в пул. Родственный интерфейс Callable: метод call() возвращает результат и может бросать проверяемые исключения в отличие от void run(). Задачи Callable выполняются не через new Thread(...), а через ExecutorService.submit(), который возвращает Future для получения результата. Пример кода Что использовать на практике Runnable — стандартный выбор: задача отделена от потока, её мо
callableexecutor