Что выведет код?
#Tasks
import java.util.*;
public class Task211124_1 {
public static void main(String[] args) {
List<String> items = Arrays.asList("A", "B", "C", "D", "E", "F", "G", "H", "I", "J");
int pageSize = 3;
int page = 3;
List<String> pageItems = paginate(items, page, pageSize);
System.out.println(pageItems);
}
public static List<String> paginate(List<String> items, int page, int pageSize) {
int start = (page - 1) * pageSize;
int end = Math.min(start + pageSize, items.size());
return items.subList(start, end);
}
}
#Tasks
Создание методов для поиска данных в Spring Data JPA
Spring Data JPA позволяет разработчикам создавать методы для поиска данных без написания SQL-запросов. Это достигается благодаря методам запроса на основе имен и JPQL-запросам.
Методы поиска по имени
Spring Data позволяет создавать методы поиска, просто добавляя определенные суффиксы в их имена.
Примеры методов поиска:
findBy — находит по полю.
findBy...And... — находит по нескольким полям.
findBy...Or... — находит по одному из нескольких полей.
Предположим, у нас есть сущность User:
Теперь создадим репозиторий:
Использование этих методов:
Методы с использованием JPQL
JPQL (Java Persistence Query Language) — это язык запросов, похожий на SQL, но использующий сущности вместо таблиц. В Spring Data JPA вы можете использовать JPQL-запросы с аннотацией @Query.
Добавим метод с JPQL-запросом в UserRepository:
Теперь мы можем использовать эти методы для более гибкого поиска:
Сортировка и пагинация
Spring Data JPA позволяет легко добавлять сортировку и пагинацию к любым методам поиска.
Пример с использованием сортировки:
Пример с пагинацией:
#Java #Training #Spring #JPQL
Spring Data JPA позволяет разработчикам создавать методы для поиска данных без написания SQL-запросов. Это достигается благодаря методам запроса на основе имен и JPQL-запросам.
Методы поиска по имени
Spring Data позволяет создавать методы поиска, просто добавляя определенные суффиксы в их имена.
Примеры методов поиска:
findBy — находит по полю.
findBy...And... — находит по нескольким полям.
findBy...Or... — находит по одному из нескольких полей.
Предположим, у нас есть сущность User:
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue
private Long id;
private String name;
private String email;
// getters and setters
}
Теперь создадим репозиторий:
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByName(String name);
User findByEmail(String email);
List<User> findByNameAndEmail(String name, String email);
}
Использование этих методов:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public List<User> getUsersByName(String name) {
return userRepository.findByName(name);
}
public User getUserByEmail(String email) {
return userRepository.findByEmail(email);
}
public List<User> getUsersByNameAndEmail(String name, String email) {
return userRepository.findByNameAndEmail(name, email);
}
}
Методы с использованием JPQL
JPQL (Java Persistence Query Language) — это язык запросов, похожий на SQL, но использующий сущности вместо таблиц. В Spring Data JPA вы можете использовать JPQL-запросы с аннотацией @Query.
Добавим метод с JPQL-запросом в UserRepository:
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface UserRepository extends JpaRepository<User, Long> {
@Query("SELECT u FROM User u WHERE u.name = :name")
List<User> findUsersByName(@Param("name") String name);
@Query("SELECT u FROM User u WHERE u.email LIKE %:emailDomain")
List<User> findUsersByEmailDomain(@Param("emailDomain") String emailDomain);
}
Теперь мы можем использовать эти методы для более гибкого поиска:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public List<User> findUsersByEmailDomain(String domain) {
return userRepository.findUsersByEmailDomain(domain);
}
}
Сортировка и пагинация
Spring Data JPA позволяет легко добавлять сортировку и пагинацию к любым методам поиска.
Пример с использованием сортировки:
import org.springframework.data.domain.Sort;
List<User> findAll(Sort sort);
List<User> usersSortedByName = userRepository.findAll(Sort.by("name"));
Пример с пагинацией:
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
Page<User> findAll(PageRequest pageable);
Page<User> usersPage = userRepository.findAll(PageRequest.of(0, 10));
#Java #Training #Spring #JPQL
Что выведет код?
Задача по Spring JDBC, JPQL, @JpaRepository, @Entity, @Table, @Id создание и выполнение CRUD операций в Spring. Сложность легкая.
Подробный разбор через 30 минут!🫡
#TasksSpring
Задача по Spring JDBC, JPQL, @JpaRepository, @Entity, @Table, @Id создание и выполнение CRUD операций в Spring. Сложность легкая.
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import java.util.List;
@SpringBootApplication
public class Main211124_2 {
public static void main(String[] args) {
SpringApplication.run(Main211124_2.class, args);
}
@Bean
public CommandLineRunner demo(UserRepository2111 repository) {
return args -> {
repository.save(new User2111("Alice", 30));
repository.save(new User2111("Bob", 25));
List<User2111> users = repository.findByAgeGreaterThan(20);
users.forEach(user -> System.out.println(user.getName()));
};
}
}
@Entity
@Table(name = "users2111")
class User2111 {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private int age;
// Конструкторы, геттеры и сеттеры
public User2111() {}
public User2111(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
}
@Repository
interface UserRepository2111 extends JpaRepository<User2111, Long> {
List<User2111> findByAgeGreaterThan(int age);
}
#TasksSpring
Подробный разбор решения задачи Task211124_2
1. Контекст задачи:
Задача демонстрирует использование Spring Data JPA для работы с базой данных. В частности, она показывает, как использовать аннотации JPA (@Entity, @Table, @Id) для определения сущностей, а также JpaRepository для выполнения CRUD операций и запросов с использованием JPQL. Основное внимание уделяется выполнению операций сохранения и выборки данных.
2. Ключевые элементы кода:
Аннотация @SpringBootApplication:
Указывает, что класс Main211124_2 является главным классом Spring Boot приложения. Она включает в себя @Configuration, @EnableAutoConfiguration, и @ComponentScan, что автоматически настраивает компоненты Spring, включая Spring Data JPA.
Аннотация @Entity:
Класс User2111 помечен аннотацией @Entity, что указывает JPA, что этот класс соответствует таблице в базе данных. Он представляет собой сущность, с которой будет работать JPA.
Аннотация @Table(name = "users2111"):
Определяет, что эта сущность будет сопоставлена с таблицей users2111 в базе данных. Если аннотация @Table не указана, JPA по умолчанию использует имя класса как имя таблицы.
Аннотация @Id и @GeneratedValue:
Поле id помечено как первичный ключ с помощью аннотации @Id.
Аннотация @GeneratedValue(strategy = GenerationType.AUTO) указывает, что значение для поля id будет генерироваться автоматически (обычно с использованием автоинкремента в базе данных).
Интерфейс UserRepository2111 и аннотация @Repository:
UserRepository2111 расширяет JpaRepository, что предоставляет стандартные методы CRUD (например, save, findAll, deleteById).
Метод findByAgeGreaterThan(int age) позволяет выполнять JPQL-запрос для получения всех пользователей, у которых возраст больше заданного.
Использование CommandLineRunner:
CommandLineRunner используется для выполнения кода сразу после запуска приложения. В данном случае он выполняет следующие шаги:
Сохраняет в базу данных двух пользователей: "Alice" с возрастом 30 и "Bob" с возрастом 25.
Выполняет запрос findByAgeGreaterThan(20), возвращающий всех пользователей с возрастом больше 20.
Выводит имена выбранных пользователей в консоль.
3. Сценарий работы программы:
Запуск приложения:
Программа запускается с помощью SpringApplication.run(Main211124_2.class, args);. Spring Boot настраивает подключение к базе данных и компоненты Spring Data JPA.
Вставка данных:
Метод save() из JpaRepository используется для сохранения двух записей:
User2111("Alice", 30)
User2111("Bob", 25)
Выполнение запроса:
Метод findByAgeGreaterThan(20) выбирает всех пользователей, у которых возраст больше 20. Это JPQL-запрос, автоматически формируемый Spring Data JPA на основе имени метода.
Вывод данных:
Полученные записи проходят через метод forEach, который вызывает System.out.println для вывода имен в консоль.
4. Ключевые моменты и выводы:
Использование JPA и Spring Data:
Spring Data JPA значительно упрощает работу с базой данных, предоставляя готовые методы для выполнения CRUD операций и поддерживая создание запросов на основе имен методов.
Аннотации JPA:
@Entity и @Table используются для связывания класса с таблицей в базе данных.
@Id и @GeneratedValue обеспечивают автоматическую генерацию уникальных идентификаторов для каждой записи.
JPQL-запросы и JpaRepository:
Метод findByAgeGreaterThan демонстрирует, как можно выполнять запросы к базе данных, просто определяя метод с соответствующим именем в репозитории.
Гибкость CommandLineRunner:
Использование CommandLineRunner позволяет запускать код после загрузки контекста Spring, что удобно для тестирования операций с базой данных.
#Solution_TasksSpring
1. Контекст задачи:
Задача демонстрирует использование Spring Data JPA для работы с базой данных. В частности, она показывает, как использовать аннотации JPA (@Entity, @Table, @Id) для определения сущностей, а также JpaRepository для выполнения CRUD операций и запросов с использованием JPQL. Основное внимание уделяется выполнению операций сохранения и выборки данных.
2. Ключевые элементы кода:
Аннотация @SpringBootApplication:
Указывает, что класс Main211124_2 является главным классом Spring Boot приложения. Она включает в себя @Configuration, @EnableAutoConfiguration, и @ComponentScan, что автоматически настраивает компоненты Spring, включая Spring Data JPA.
Аннотация @Entity:
Класс User2111 помечен аннотацией @Entity, что указывает JPA, что этот класс соответствует таблице в базе данных. Он представляет собой сущность, с которой будет работать JPA.
Аннотация @Table(name = "users2111"):
Определяет, что эта сущность будет сопоставлена с таблицей users2111 в базе данных. Если аннотация @Table не указана, JPA по умолчанию использует имя класса как имя таблицы.
Аннотация @Id и @GeneratedValue:
Поле id помечено как первичный ключ с помощью аннотации @Id.
Аннотация @GeneratedValue(strategy = GenerationType.AUTO) указывает, что значение для поля id будет генерироваться автоматически (обычно с использованием автоинкремента в базе данных).
Интерфейс UserRepository2111 и аннотация @Repository:
UserRepository2111 расширяет JpaRepository, что предоставляет стандартные методы CRUD (например, save, findAll, deleteById).
Метод findByAgeGreaterThan(int age) позволяет выполнять JPQL-запрос для получения всех пользователей, у которых возраст больше заданного.
Использование CommandLineRunner:
CommandLineRunner используется для выполнения кода сразу после запуска приложения. В данном случае он выполняет следующие шаги:
Сохраняет в базу данных двух пользователей: "Alice" с возрастом 30 и "Bob" с возрастом 25.
Выполняет запрос findByAgeGreaterThan(20), возвращающий всех пользователей с возрастом больше 20.
Выводит имена выбранных пользователей в консоль.
3. Сценарий работы программы:
Запуск приложения:
Программа запускается с помощью SpringApplication.run(Main211124_2.class, args);. Spring Boot настраивает подключение к базе данных и компоненты Spring Data JPA.
Вставка данных:
Метод save() из JpaRepository используется для сохранения двух записей:
User2111("Alice", 30)
User2111("Bob", 25)
Выполнение запроса:
Метод findByAgeGreaterThan(20) выбирает всех пользователей, у которых возраст больше 20. Это JPQL-запрос, автоматически формируемый Spring Data JPA на основе имени метода.
Вывод данных:
Полученные записи проходят через метод forEach, который вызывает System.out.println для вывода имен в консоль.
4. Ключевые моменты и выводы:
Использование JPA и Spring Data:
Spring Data JPA значительно упрощает работу с базой данных, предоставляя готовые методы для выполнения CRUD операций и поддерживая создание запросов на основе имен методов.
Аннотации JPA:
@Entity и @Table используются для связывания класса с таблицей в базе данных.
@Id и @GeneratedValue обеспечивают автоматическую генерацию уникальных идентификаторов для каждой записи.
JPQL-запросы и JpaRepository:
Метод findByAgeGreaterThan демонстрирует, как можно выполнять запросы к базе данных, просто определяя метод с соответствующим именем в репозитории.
Гибкость CommandLineRunner:
Использование CommandLineRunner позволяет запускать код после загрузки контекста Spring, что удобно для тестирования операций с базой данных.
#Solution_TasksSpring
Транзакции в Spring
В современных приложениях, особенно тех, что работают с базами данных, транзакции играют ключевую роль. Они обеспечивают выполнение операций в базе данных с гарантией целостности данных и устойчивости к сбоям.
Транзакция — это последовательность операций, которые выполняются как единое целое. Если хотя бы одна из операций в транзакции завершается с ошибкой, все изменения, сделанные в рамках этой транзакции, откатываются.
Ключевые свойства транзакций определяются через ACID:
Atomicity (Атомарность): Все операции в транзакции выполняются или ни одна из них.
Consistency (Согласованность): Транзакция переводит базу данных из одного согласованного состояния в другое.
Isolation (Изолированность): Операции в транзакции не видимы другим транзакциям, пока они не завершатся.
Durability (Устойчивость): После успешного завершения транзакции изменения остаются сохраненными в базе данных, даже в случае сбоя системы.
Пример транзакции в SQL
Предположим, у нас есть две таблицы: accounts и transactions. Нам нужно перевести деньги с одного счета на другой.
Транзакции в Spring
Spring обеспечивает управление транзакциями с помощью своих инструментов.
В экосистеме Spring можно использовать различные подходы:
Программное управление транзакциями — требуется вручную управлять началом и завершением транзакций.
Декларативное управление транзакциями — управление транзакциями осуществляется автоматически с помощью аннотаций или конфигураций. Этот подход является наиболее популярным, так как упрощает код.
Программное управление транзакциями
Для ручного управления транзакциями в Spring используется PlatformTransactionManager.
Пример:
Декларативное управление транзакциями
Более простой и популярный способ — это использование аннотации @Transactional.
Преимущества транзакций:
Целостность данных: Транзакции гарантируют, что данные останутся в корректном состоянии.
Стабильность системы: Операции либо полностью завершаются, либо полностью откатываются.
Упрощение отладки: Вы можете быть уверены, что в случае сбоя данные не будут повреждены.
#Java #Training #Spring #Transactions #ACID
В современных приложениях, особенно тех, что работают с базами данных, транзакции играют ключевую роль. Они обеспечивают выполнение операций в базе данных с гарантией целостности данных и устойчивости к сбоям.
Транзакция — это последовательность операций, которые выполняются как единое целое. Если хотя бы одна из операций в транзакции завершается с ошибкой, все изменения, сделанные в рамках этой транзакции, откатываются.
Ключевые свойства транзакций определяются через ACID:
Atomicity (Атомарность): Все операции в транзакции выполняются или ни одна из них.
Consistency (Согласованность): Транзакция переводит базу данных из одного согласованного состояния в другое.
Isolation (Изолированность): Операции в транзакции не видимы другим транзакциям, пока они не завершатся.
Durability (Устойчивость): После успешного завершения транзакции изменения остаются сохраненными в базе данных, даже в случае сбоя системы.
Пример транзакции в SQL
Предположим, у нас есть две таблицы: accounts и transactions. Нам нужно перевести деньги с одного счета на другой.
BEGIN TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
INSERT INTO transactions (from_account, to_account, amount) VALUES (1, 2, 100);
COMMIT;
Если любая из этих операций не выполняется, все изменения откатываются.
Транзакции в Spring
Spring обеспечивает управление транзакциями с помощью своих инструментов.
В экосистеме Spring можно использовать различные подходы:
Программное управление транзакциями — требуется вручную управлять началом и завершением транзакций.
Декларативное управление транзакциями — управление транзакциями осуществляется автоматически с помощью аннотаций или конфигураций. Этот подход является наиболее популярным, так как упрощает код.
Программное управление транзакциями
Для ручного управления транзакциями в Spring используется PlatformTransactionManager.
Пример:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
@Service
public class TransactionalService {
@Autowired
private PlatformTransactionManager transactionManager;
public void performTransactionalOperation() {
TransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(def);
try {
// Ваши операции с базой данных
performDatabaseOperation1();
performDatabaseOperation2();
// Подтверждение транзакции
transactionManager.commit(status);
} catch (Exception e) {
// Откат транзакции в случае ошибки
transactionManager.rollback(status);
throw e;
}
}
private void performDatabaseOperation1() {
// Код операции 1
}
private void performDatabaseOperation2() {
// Код операции 2
}
}
Этот метод предоставляет полный контроль над транзакциями, но делает код более сложным.
Декларативное управление транзакциями
Более простой и популярный способ — это использование аннотации @Transactional.
Преимущества транзакций:
Целостность данных: Транзакции гарантируют, что данные останутся в корректном состоянии.
Стабильность системы: Операции либо полностью завершаются, либо полностью откатываются.
Упрощение отладки: Вы можете быть уверены, что в случае сбоя данные не будут повреждены.
#Java #Training #Spring #Transactions #ACID
Продолжаем устранять пробелы в многопоточке Java. Сегодня рассмотрим Semaphore и CountDownLatch.
Semaphore
Semaphore используется для управления доступом к ограниченному ресурсу, который может одновременно использоваться только определенным числом потоков. Это полезно для реализации пула ресурсов, например, подключения к базе данных, файловых дескрипторов и других ограниченных ресурсов.
Основные методы Semaphore
acquire(): Захватывает разрешение (пермит). Если разрешений нет, поток блокируется до тех пор, пока одно из них не станет доступным.
acquire(int permits): Захватывает указанное количество разрешений. Если их недостаточно, поток блокируется.
release(): Освобождает разрешение, увеличивая количество доступных разрешений на 1.
release(int permits): Освобождает указанное количество разрешений.
availablePermits(): Возвращает количество доступных разрешений.
tryAcquire(): Пытается захватить разрешение. Возвращает true, если удалось получить разрешение, иначе false.
tryAcquire(int permits, long timeout, TimeUnit unit): Пытается получить разрешения с указанным временем ожидания.
isFair(): Проверяет, использует ли семафор справедливый порядок захвата разрешений (FIFO).
Типы Semaphore
Несправедливый (non-fair): Потоки получают доступ в произвольном порядке (по умолчанию).
Справедливый (fair): Потоки получают доступ в порядке очереди (FIFO).
Пример использования Semaphore
Результат:
В каждый момент времени только 2 потока выполняют свою работу.
Остальные ждут освобождения разрешения.
Нюансы Semaphore
Справедливость (fair vs non-fair):
Несправедливый семафор быстрее, но поток может быть отложен, даже если он ожидает дольше других.
Справедливый семафор обеспечивает порядок очереди, но имеет больше накладных расходов.
Deadlock (взаимная блокировка):
Если поток забывает вызвать release() после acquire(), это приведет к "утечке" разрешений.
Пул ресурсов:
Часто используется для ограничения числа потоков, работающих с одним и тем же ресурсом.
#Java #Training #Multithreading #Semaphore
Semaphore
Semaphore используется для управления доступом к ограниченному ресурсу, который может одновременно использоваться только определенным числом потоков. Это полезно для реализации пула ресурсов, например, подключения к базе данных, файловых дескрипторов и других ограниченных ресурсов.
Основные методы Semaphore
acquire(): Захватывает разрешение (пермит). Если разрешений нет, поток блокируется до тех пор, пока одно из них не станет доступным.
acquire(int permits): Захватывает указанное количество разрешений. Если их недостаточно, поток блокируется.
release(): Освобождает разрешение, увеличивая количество доступных разрешений на 1.
release(int permits): Освобождает указанное количество разрешений.
availablePermits(): Возвращает количество доступных разрешений.
tryAcquire(): Пытается захватить разрешение. Возвращает true, если удалось получить разрешение, иначе false.
tryAcquire(int permits, long timeout, TimeUnit unit): Пытается получить разрешения с указанным временем ожидания.
isFair(): Проверяет, использует ли семафор справедливый порядок захвата разрешений (FIFO).
Типы Semaphore
Несправедливый (non-fair): Потоки получают доступ в произвольном порядке (по умолчанию).
Справедливый (fair): Потоки получают доступ в порядке очереди (FIFO).
Пример использования Semaphore
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
public static void main(String[] args) {
// Семафор с 2 разрешениями
Semaphore semaphore = new Semaphore(2);
// Пул из 5 потоков
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
final int threadId = i;
executor.submit(() -> {
try {
System.out.println("Thread " + threadId + " is waiting for permit...");
semaphore.acquire(); // Получаем разрешение
System.out.println("Thread " + threadId + " acquired permit.");
Thread.sleep(2000); // Имитируем использование ресурса
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
System.out.println("Thread " + threadId + " released permit.");
semaphore.release(); // Освобождаем разрешение
}
});
}
executor.shutdown();
}
}
Результат:
В каждый момент времени только 2 потока выполняют свою работу.
Остальные ждут освобождения разрешения.
Нюансы Semaphore
Справедливость (fair vs non-fair):
Несправедливый семафор быстрее, но поток может быть отложен, даже если он ожидает дольше других.
Справедливый семафор обеспечивает порядок очереди, но имеет больше накладных расходов.
Deadlock (взаимная блокировка):
Если поток забывает вызвать release() после acquire(), это приведет к "утечке" разрешений.
Пул ресурсов:
Часто используется для ограничения числа потоков, работающих с одним и тем же ресурсом.
#Java #Training #Multithreading #Semaphore
CountDownLatch
CountDownLatch используется для обеспечения синхронизации между потоками, позволяя одному или нескольким потокам ждать завершения операций в других потоках.
Основные методы CountDownLatch
await(): Блокирует поток до тех пор, пока счетчик не станет равен 0.
countDown(): Уменьшает значение счетчика на 1.
getCount(): Возвращает текущее значение счетчика.
await(long timeout, TimeUnit unit): Ждет заданное время. Если счетчик не достигает 0 за указанное время, поток продолжит выполнение.
Пример использования CountDownLatch
Результат:
Основной поток будет ждать завершения всех 3 задач.
После выполнения всех потоков (latch.countDown() вызывается 3 раза), основной поток продолжит выполнение.
Нюансы CountDownLatch
Одноразовый:
CountDownLatch нельзя сбросить или переиспользовать. Если нужно использовать его несколько раз, рассмотрите использование CyclicBarrier.
Потокобезопасность:
Все методы потокобезопасны и могут использоваться несколькими потоками одновременно.
Применение:
Инициализация или подготовка перед началом основной работы.
Ожидание завершения группы задач.
Когда использовать Semaphore или CountDownLatch?
Используйте Semaphore, если нужно управлять доступом к ограниченным ресурсам (например, пул соединений).
Используйте CountDownLatch, если потоки должны дождаться выполнения определенного количества задач, прежде чем продолжить выполнение.
Реальные примеры
Semaphore: Ограничение количества одновременных соединений
CountDownLatch: Ожидание завершения загрузки данных
#Java #Training #Multithreading #CountDownLatch
CountDownLatch используется для обеспечения синхронизации между потоками, позволяя одному или нескольким потокам ждать завершения операций в других потоках.
Основные методы CountDownLatch
await(): Блокирует поток до тех пор, пока счетчик не станет равен 0.
countDown(): Уменьшает значение счетчика на 1.
getCount(): Возвращает текущее значение счетчика.
await(long timeout, TimeUnit unit): Ждет заданное время. Если счетчик не достигает 0 за указанное время, поток продолжит выполнение.
Пример использования CountDownLatch
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
// Создаем CountDownLatch с начальным значением 3
CountDownLatch latch = new CountDownLatch(3);
// Потоки, выполняющие задачи
Runnable task = () -> {
System.out.println(Thread.currentThread().getName() + " is working...");
try {
Thread.sleep(1000); // Имитация работы
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println(Thread.currentThread().getName() + " finished.");
latch.countDown(); // Уменьшаем значение счетчика
};
// Запускаем 3 потока
for (int i = 0; i < 3; i++) {
new Thread(task).start();
}
System.out.println("Main thread is waiting for tasks to finish...");
latch.await(); // Ждем, пока счетчик не станет равен 0
System.out.println("All tasks are finished. Main thread resumes.");
}
}
Результат:
Основной поток будет ждать завершения всех 3 задач.
После выполнения всех потоков (latch.countDown() вызывается 3 раза), основной поток продолжит выполнение.
Нюансы CountDownLatch
Одноразовый:
CountDownLatch нельзя сбросить или переиспользовать. Если нужно использовать его несколько раз, рассмотрите использование CyclicBarrier.
Потокобезопасность:
Все методы потокобезопасны и могут использоваться несколькими потоками одновременно.
Применение:
Инициализация или подготовка перед началом основной работы.
Ожидание завершения группы задач.
Когда использовать Semaphore или CountDownLatch?
Используйте Semaphore, если нужно управлять доступом к ограниченным ресурсам (например, пул соединений).
Используйте CountDownLatch, если потоки должны дождаться выполнения определенного количества задач, прежде чем продолжить выполнение.
Реальные примеры
Semaphore: Ограничение количества одновременных соединений
Semaphore semaphore = new Semaphore(10); // Максимум 10 соединений
// Каждый поток пытается установить соединение
Runnable connectTask = () -> {
try {
semaphore.acquire();
System.out.println("Connection established by " + Thread.currentThread().getName());
Thread.sleep(2000); // Используем соединение
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
System.out.println("Connection released by " + Thread.currentThread().getName());
semaphore.release();
}
};
CountDownLatch: Ожидание завершения загрузки данных
CountDownLatch latch = new CountDownLatch(3);
Runnable loadData = () -> {
try {
System.out.println(Thread.currentThread().getName() + " loading data...");
Thread.sleep(1000);
latch.countDown();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
};
new Thread(loadData).start();
new Thread(loadData).start();
new Thread(loadData).start();
latch.await();
System.out.println("All data loaded. Proceeding to next step.");
#Java #Training #Multithreading #CountDownLatch
Что выведет код?
#Tasks
public class Task221124_1 {
public static void main(String[] args) {
int[] arr = {3, 5, 7, 9, 11};
int result = modifyArray(arr);
System.out.println(result);
System.out.println(arr[1]);
}
public static int modifyArray(int[] array) {
int sum = 0;
for (int i = 0; i < array.length; i++) {
array[i] = array[i] % 2 == 0 ? array[i] / 2 : array[i] * 2;
sum += array[i];
}
return sum;
}
}
#Tasks
Аннотация @Transactional
Spring предлагает удобный способ работы с транзакциями через аннотацию @Transactional. Она позволяет использовать декларативное управление транзакциями, минимизируя количество кода и повышая читаемость.
@Transactional — это аннотация, которая может быть применена к классу или методу, чтобы указать, что в рамках данного метода или всех методов класса должна использоваться транзакция.
Пример базового использования:
Основные параметры @Transactional
@Transactional поддерживает ряд параметров, которые позволяют гибко управлять транзакциями:
propagation: Определяет, как должна быть организована транзакция при вызове метода.
REQUIRED (по умолчанию): Использует текущую транзакцию или создает новую.
REQUIRES_NEW: Всегда создает новую транзакцию.
NESTED: Создает вложенную транзакцию.
SUPPORTS: Метод может работать в контексте транзакции, но это не обязательно.
isolation: Уровень изоляции транзакции.
READ_UNCOMMITTED: Минимальная изоляция, данные могут быть "грязными".
READ_COMMITTED: Предотвращает "грязное" чтение.
REPEATABLE_READ: Предотвращает неповторяющееся чтение.
SERIALIZABLE: Максимальная изоляция, предотвращает все виды конфликтов.
timeout: Максимальное время выполнения транзакции в секундах.
readOnly: Указывает, что транзакция предназначена только для чтения данных.
rollbackFor и noRollbackFor: Исключения, при которых следует или не следует откатывать транзакцию.
Пример с параметрами:
Управление откатами
Spring автоматически откатывает транзакции, если метод генерирует RuntimeException или Error. Вы можете настроить это поведение с помощью rollbackFor.
Применение @Transactional на уровне класса
Если аннотация используется на уровне класса, все методы будут выполняться в рамках транзакции.
Особенности работы с @Transactional
Прокси: Spring использует прокси-объекты для управления транзакциями. Это означает, что вызовы методов внутри одного класса могут не учитывать аннотацию @Transactional.
Пример проблемы:
#Java #Training #Spring #Transactional
Spring предлагает удобный способ работы с транзакциями через аннотацию @Transactional. Она позволяет использовать декларативное управление транзакциями, минимизируя количество кода и повышая читаемость.
@Transactional — это аннотация, которая может быть применена к классу или методу, чтобы указать, что в рамках данного метода или всех методов класса должна использоваться транзакция.
Пример базового использования:
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class PaymentService {
@Transactional
public void transferMoney(Long fromAccountId, Long toAccountId, double amount) {
// Операции с базой данных
debitAccount(fromAccountId, amount);
creditAccount(toAccountId, amount);
}
private void debitAccount(Long accountId, double amount) {
// Логика снятия средств
}
private void creditAccount(Long accountId, double amount) {
// Логика зачисления средств
}
}
В этом примере все операции внутри метода transferMoney выполняются в одной транзакции. Если любая операция завершится сбоем, все изменения будут откатаны.
Основные параметры @Transactional
@Transactional поддерживает ряд параметров, которые позволяют гибко управлять транзакциями:
propagation: Определяет, как должна быть организована транзакция при вызове метода.
REQUIRED (по умолчанию): Использует текущую транзакцию или создает новую.
REQUIRES_NEW: Всегда создает новую транзакцию.
NESTED: Создает вложенную транзакцию.
SUPPORTS: Метод может работать в контексте транзакции, но это не обязательно.
isolation: Уровень изоляции транзакции.
READ_UNCOMMITTED: Минимальная изоляция, данные могут быть "грязными".
READ_COMMITTED: Предотвращает "грязное" чтение.
REPEATABLE_READ: Предотвращает неповторяющееся чтение.
SERIALIZABLE: Максимальная изоляция, предотвращает все виды конфликтов.
timeout: Максимальное время выполнения транзакции в секундах.
readOnly: Указывает, что транзакция предназначена только для чтения данных.
rollbackFor и noRollbackFor: Исключения, при которых следует или не следует откатывать транзакцию.
Пример с параметрами:
@Transactional(
propagation = Propagation.REQUIRES_NEW,
isolation = Isolation.SERIALIZABLE,
timeout = 30,
rollbackFor = {RuntimeException.class},
readOnly = false
)
public void processTransaction() {
// Логика транзакции
}
Управление откатами
Spring автоматически откатывает транзакции, если метод генерирует RuntimeException или Error. Вы можете настроить это поведение с помощью rollbackFor.
@Transactional(rollbackFor = Exception.class)
public void updateDatabase() throws Exception {
// Если возникает Exception, транзакция будет откатана
}
Применение @Transactional на уровне класса
Если аннотация используется на уровне класса, все методы будут выполняться в рамках транзакции.
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class OrderService {
public void createOrder() {
// Операции в транзакции
}
public void cancelOrder() {
// Операции в транзакции
}
}
Особенности работы с @Transactional
Прокси: Spring использует прокси-объекты для управления транзакциями. Это означает, что вызовы методов внутри одного класса могут не учитывать аннотацию @Transactional.
Пример проблемы:
@Service
public class ExampleService {
@Transactional
public void method1() {
method2(); // method2 вызван напрямую, @Transactional не применяется
}
@Transactional
public void method2() {
// Логика method2
}
}
Только публичные методы: Аннотация работает только на публичных методах. Внутренние вызовы приватных или protected методов не активируют транзакцию.
#Java #Training #Spring #Transactional
Всем доброго субботнего утра!✌️
Вот и пришли выходные, а с ними и завтрашний лайф-кодинг.
В этот раз мы напишем на Spring простой банковский сервис, главной фишкой которого является асинхронная обработка всех поступающих запросов на перевод денег между клиентами.
Также в рамках написания, мы рассмотрим основные вопросы многопоточноcти в Java.
А в остальном всем теплых и светлых выходных!🫡
Вот и пришли выходные, а с ними и завтрашний лайф-кодинг.
В этот раз мы напишем на Spring простой банковский сервис, главной фишкой которого является асинхронная обработка всех поступающих запросов на перевод денег между клиентами.
Также в рамках написания, мы рассмотрим основные вопросы многопоточноcти в Java.
А в остальном всем теплых и светлых выходных!🫡
This media is not supported in your browser
VIEW IN TELEGRAM
Всем привет!🖐
Сегодня в 16:00 по МСК жду Вас на лайф-кодинге! 😱
Напишем на Spring простое банковское CRUD-приложение с упором на многопоточку и протестируем его.
Ссылку на Яндекс.Телемост опубликую здесь за 15 минут до начала.✌️
До встречи!🤓
Сегодня в 16:00 по МСК жду Вас на лайф-кодинге! 😱
Напишем на Spring простое банковское CRUD-приложение с упором на многопоточку и протестируем его.
Ссылку на Яндекс.Телемост опубликую здесь за 15 минут до начала.✌️
До встречи!🤓
Оглавление обучающих постов часть 3. SPRING
Spring Framework
Архитектура Spring и его модули
Spring Framework's
Контейнер Inversion of Control (IoC)
Принципы Dependency Injection (DI)
Управление объектами в Spring Container
Конфигурация Spring через XML
Конфигурация Spring через аннотации
Основы Bean в Spring: создание и управление
Жизненный цикл бинов
Синглтон и Прототипы в Spring
Паттерны использования бинов в Spring
Spring. Внедрение зависимостей через конструктор
Spring. Внедрение зависимостей через сеттеры
@Autowired
@Qualifier
Контекст Spring: ApplicationContext и BeanFactory
Способы загрузки контекста в Spring
Жизненный цикл ApplicationContext в Spring
Построение приложения с использованием Java-конфигурации в Spring
@Component и @Service
@Repository в Spring
Способы работы с внешними конфигурациями в Spring: application.properties и application.yml
Валидация и валидационные аннотации в Spring
@Import
@Value
——SPRING MVC——
Spring MVC
Архитектура MVC в Spring
@Controller
@RequestMapping
@GetMapping, @PostMapping, @PutMapping и @DeleteMapping
@RequestBody
@ModelAttribute
@RequestParam и @PathVariable
ViewResolver
@ResponseBody
Как @RestController взаимодействует с @RequestMapping
JSP и Thymeleaf как механизмы представления
Конфигурация шаблонов Thymeleaf в Spring
Формы и отправка данных в Spring MVC
Обработка форм и привязка данных в Spring MVC
@ExceptionHandler
@ControllerAdvice
——SPRING JDBC——
Введение в Spring JDBC
Настройка DataSource и подключение к базе данных в Spring JDBC
Использование JdbcTemplate в Spring JDBC для выполнения SQL-запросов
Создание и выполнение CRUD операций через Spring JDBC
Введение в ORM и Spring Data JPA
@Entity, @Table, @Id
@Column, @GeneratedValue, @ManyToOne
@OneToOne, @ManyToMany, @JoinColumn, @Lob, @Query, @Modifying, @EnableJpaRepositories
@Embeddable, @Embedded, @ElementCollection, @Inheritance, @Cacheable, @Lock, @EntityListeners, @SQLInsert, @SQLUpdate, @SQLDelete
Сущности в JPA
Репозитории в Spring Data: интерфейс CrudRepository и JpaRepository
Создание методов для поиска данных в Spring Data JPA
Транзакции в Spring
@Transactional
Уровни изоляции транзакций и виды проблем
Управление транзакциями вручную
Rollback и Commit транзакций
Rollback с использованием @Transactional
Исключения в транзакциях
Оптимизация работы с транзакциями
Нюансы работы с транзакциями в Spring
#Contents
Spring Framework
Архитектура Spring и его модули
Spring Framework's
Контейнер Inversion of Control (IoC)
Принципы Dependency Injection (DI)
Управление объектами в Spring Container
Конфигурация Spring через XML
Конфигурация Spring через аннотации
Основы Bean в Spring: создание и управление
Жизненный цикл бинов
Синглтон и Прототипы в Spring
Паттерны использования бинов в Spring
Spring. Внедрение зависимостей через конструктор
Spring. Внедрение зависимостей через сеттеры
@Autowired
@Qualifier
Контекст Spring: ApplicationContext и BeanFactory
Способы загрузки контекста в Spring
Жизненный цикл ApplicationContext в Spring
Построение приложения с использованием Java-конфигурации в Spring
@Component и @Service
@Repository в Spring
Способы работы с внешними конфигурациями в Spring: application.properties и application.yml
Валидация и валидационные аннотации в Spring
@Import
@Value
——SPRING MVC——
Spring MVC
Архитектура MVC в Spring
@Controller
@RequestMapping
@GetMapping, @PostMapping, @PutMapping и @DeleteMapping
@RequestBody
@ModelAttribute
@RequestParam и @PathVariable
ViewResolver
@ResponseBody
Как @RestController взаимодействует с @RequestMapping
JSP и Thymeleaf как механизмы представления
Конфигурация шаблонов Thymeleaf в Spring
Формы и отправка данных в Spring MVC
Обработка форм и привязка данных в Spring MVC
@ExceptionHandler
@ControllerAdvice
——SPRING JDBC——
Введение в Spring JDBC
Настройка DataSource и подключение к базе данных в Spring JDBC
Использование JdbcTemplate в Spring JDBC для выполнения SQL-запросов
Создание и выполнение CRUD операций через Spring JDBC
Введение в ORM и Spring Data JPA
@Entity, @Table, @Id
@Column, @GeneratedValue, @ManyToOne
@OneToOne, @ManyToMany, @JoinColumn, @Lob, @Query, @Modifying, @EnableJpaRepositories
@Embeddable, @Embedded, @ElementCollection, @Inheritance, @Cacheable, @Lock, @EntityListeners, @SQLInsert, @SQLUpdate, @SQLDelete
Сущности в JPA
Репозитории в Spring Data: интерфейс CrudRepository и JpaRepository
Создание методов для поиска данных в Spring Data JPA
Транзакции в Spring
@Transactional
Уровни изоляции транзакций и виды проблем
Управление транзакциями вручную
Rollback и Commit транзакций
Rollback с использованием @Transactional
Исключения в транзакциях
Оптимизация работы с транзакциями
Нюансы работы с транзакциями в Spring
#Contents
Оглавление для обучающих постов.
Если хотите найти информацию по Java, ранее опубликованную на канале - для Вас подготовлено оглавление уже из 3-х частей!
Пользуйтесь на здоровье!🫡
Часть 1.
Часть 2.
Часть 3. SPRING
Часть 2 дополнена.
Читайте, используйте, будут вопросы - пишите!😉
Если хотите найти информацию по Java, ранее опубликованную на канале - для Вас подготовлено оглавление уже из 3-х частей!
Пользуйтесь на здоровье!🫡
Часть 1.
Часть 2.
Часть 3. SPRING
Часть 2 дополнена.
Читайте, используйте, будут вопросы - пишите!😉
Простое Web приложение с асинхронной работой методов на Spring. Встреча от 24.11.2024
Запись нашей сегодняшней встречи -
YOUTUBE
RUTUBE
Спасибо всем кто пришел, за участие!💪
На сегодняшней встрече мы на примере, написали простое банковское Web приложение с асинхронной работой метода перевода денег на Spring. Дополнительно к постам в канале коротко разобрали работу каждой использованной аннотации, класса и метода.
Кроме того в тесте к данному приложению рассмотрели различные варианты использования методов многопоточности.
Смотрите, комментируйте, задавайте вопросы! Обязательно подписывайтесь на ютуб и рутюб каналы!!!
Ссылка на GitHub - https://github.com/Oleborn/MultiThreadingSpringApp
Всем хорошего настроения! 🫡✌️
Запись нашей сегодняшней встречи -
YOUTUBE
RUTUBE
Спасибо всем кто пришел, за участие!💪
На сегодняшней встрече мы на примере, написали простое банковское Web приложение с асинхронной работой метода перевода денег на Spring. Дополнительно к постам в канале коротко разобрали работу каждой использованной аннотации, класса и метода.
Кроме того в тесте к данному приложению рассмотрели различные варианты использования методов многопоточности.
Смотрите, комментируйте, задавайте вопросы! Обязательно подписывайтесь на ютуб и рутюб каналы!!!
Ссылка на GitHub - https://github.com/Oleborn/MultiThreadingSpringApp
Всем хорошего настроения! 🫡✌️