Jeśli mam klasy Java zdefiniowane poniżej, które wstrzykuje się w mojej aplikacji internetowych poprzez wstrzyknięcie zależności:Wiosna Singleton Bezpieczeństwo wątków
public AccountDao
{
private NamedParameterJdbcTemplate njt;
private List<Account> accounts;
public AccountDao(Datasource ds)
{
this.njt = new NamedParameterJdbcTemplate(ds);
refreshAccounts();
}
/*called at creation, and then via API calls to inform service new users have
been added to the database by a separate program*/
public void refreshAccounts()
{
this.accounts = /*call to database to get list of accounts*/
}
//called by every request to web service
public boolean isActiveAccount(String accountId)
{
Account a = map.get(accountId);
return a == null ? false : a.isActive();
}
}
Jestem zaniepokojony bezpieczeństwa wątków. Czy struktura Spring nie obsługuje przypadków, w których jedno żądanie czyta z listy i jest obecnie aktualizowane przez inne? Użyłem blokad odczytu/zapisu w innych aplikacjach, ale nigdy wcześniej nie myślałem o takim przypadku jak powyżej.
Planowałem użyć komponentu bean jako singletonu, aby zmniejszyć obciążenie bazy danych.
Nawiasem mówiąc, jest to kontynuacja się z poniższym pytaniu:
Java Memory Storage to Reduce Database Load - Safe?
EDIT:
Więc kod jak to rozwiązać ten problem:
/*called at creation, and then via API calls to inform service new users have
been added to the database by a separate program*/
public void refreshAccounts()
{
//java.util.concurrent.locks.Lock
final Lock w = lock.writeLock();
w.lock();
try{
this.accounts = /*call to database to get list of accounts*/
}
finally{
w.unlock();
}
}
//called by every request to web service
public boolean isActiveAccount(String accountId)
{
final Lock r = lock.readLock();
r.lock();
try{
Account a = map.get(accountId);
}
finally{
r.unlock();
}
return a == null ? false : a.isActive();
}
Ok, obserwacji dla zaakceptowania: Czy to naprawić łatwo poprzez kod zawarte w tej klasie Java (lub kontekst aplikacji poprawek), albo ja lepiej iść na rozwiązanie buforowanie/bazy danych? – thatidiotguy
Co można zrobić, to użyć tymczasowej listy, aby wywołać bazę danych w 'refreshAccounts()'. Kiedy to się zwróci, zsynchronizuj na 'kontach' i ponownie przypisz do tej listy. –
Powiedziałbym zdecydowanie buforowanie/bazy danych. Samo zarządzanie współbieżnością jest trudne. Dzięki buforowaniu możesz przynajmniej zapamiętywać kontrolę współbieżności.Jeśli naprawdę chciałeś dowolnej liczby żądań, zadeklarowałbym zasięg = prototyp. Następnie napotkasz problem z obciążeniem, którego dotyczyłeś. –