Добрый день.
Имеется следующая проблема. Есть сервисный класс
OrderService. У него есть метод
create(Order order, Long companyId), который перед созданием заказа проверяет не превышает ли сумма заказа баланс компании. Код класса примерно следующий.
public class OrderService {
public Order create(Order order, Long companyId) {
Company company = companyService.get(companyId);
checkCompanyBalance(company.getBalance(), order.getSum());
return create(order);
}
}
Существует вероятность того, что два пользователя создадут два заказа на компанию одновременно, при этом превысив баланс компании. Чтобы избежать этого делаем наш метод
synchronized и все. Но при этом сильно проседает производительность, потому что нет возможности создать заказ на другую компанию.
Какие есть решения у этой проблемы?
Мне приходит в голову только создать пул айдишников компаний, на которые сейчас делают заказы.
public class CompanyPool {
private Set<Long> companyIds = new HashSet<Long>();
public synchronized containsAndPut(Long companyId) {
if(companyIds.contains(companyId)) {
return false;
} else {
companyIds.add(companyId);
return true;
}
}
public synchronized remove(Long companyId) {
companyIds.remove(companyId);
}
}
и переписать метод
OrderService#create() следующим образом
public class OrderService {
private CompanyPool companyPool = new CompanyPool();
public Order create(Order order, Long companyId) {
if(companyPool.containsAndPut(companyId)) {
Company company = companyService.get(companyId);
checkCompanyBalance(company.getBalance(), order.getSum());
Order newOrder = create(order);
companyPool.remove(companyId);
return newOrder;
} else {
// wait till other thread will stop creating order for specified company
}
}
Насколько жизнеспособно подобное решение? Товарищи, может кто-то решал сходные задачи?