マルチスレッド環境下でCache機能を作る時、同時更新を防ぐためにsynchronized
をsetterに付け、getterからsetterを呼び出してあげる。
パフォーマンスのためgetterにはsynchronized
をつけない。getter内でsetterを呼ぶかどうか判断するときも、別スレッドが同時に判断した可能性があるので、setter内で再度同じ判断をしなければならない。
import java.util.Date;
import java.util.List;
import org.apache.commons.lang3.time.DateUtils;
public final class Cache {
/** コンストラクタ */
private Cache() {
}
/**
* ユーザ一覧
*/
private static List<User> allUsers = null;
/**
* ユーザ一覧の有効期限
*/
private static Date expirationOfAllUsers = new Date();
/**
* @return ユーザ一覧
*/
public static List<User> getAllUsers() {
if (expired()) {
reload();
}
return allUsers;
}
private static synchronized void reload() {
// synchronizedメソッドの中で再度、本当に取得する必要があるか確認する。
if (expired()) {
// コストの高いユーザ一覧取得処理
allUsers = highCostProc();
// 有効期限を更新
expirationOfAllUsers = DateUtils.addMinutes(new Date(), 60);
}
}
private static boolean expired() {
Date now = new Date();
return now.after(expirationOfAllUsers);
}
}