ConcurrentSkipListSet
ConcurrentSkipListSet(在JavaSE 6新增的)提供的功能类似于TreeSet,能够并发的访问有序的set。因为ConcurrentSkipListSet是基于“跳跃列表(skip list)”实现的,只要多个线程没有同时修改集合的同一个部分,那么在正常读、写集合的操作中不会出现竞争现象。
有一个业务需求,需要对用户进行增删查改的操作。
当用户第一次查询时会把所以的数据都从数据库当中查询出来。放入cache当中。
如果有增加时,会把这个新用用户放入并行集合类ConcurrentSkipListSet 当中。
删除时,数据库删除后会把这个用户信息从ConcurrentSkipListSet 中删除。
修改时。会从ConcurrentSkipListSet 中根据ID找到这个数据。然后删除。然后ADD进去。
/**
*
* @author matt.yan
*/
package uma.admin.cache;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.regex.Pattern;
import uma.admin.ws.User;
import uma.admin.ws.UserAccount;
import uma.ws.model.SourceModel.Source;
import uma.ws.model.UserAccountModel;
import uma.ws.model.UserAccountModelList;
import uma.ws.model.UserModel;
import uma.ws.model.UserModelList;
public class UserCache {
private static final UserCache usersCache = new UserCache();
private static volatile ConcurrentSkipListSet<UserModel> models = null;
public static UserCache getUsersCache() throws Exception {
if (models == null) {
synchronized (UserCache.class) {
if (models == null) {
UserModelList list = User.usersGet();
models = new ConcurrentSkipListSet<UserModel> (
new Comparator<UserModel>() {
@Override
public int compare(UserModel o1, UserModel o2) {
if(o1.getLastName() == null && o1.getFirstName() == null) {
return -1;
}
if(o2.getLastName() == null && o2.getFirstName() == null) {
return 1;
}
if(o1.getLastName() == null || o2.getLastName() == null) {
return o1.getLastName() == null ? -1 : 1;
}
int compare = o1.getLastName().trim().toUpperCase().compareTo(o2.getLastName().trim().toUpperCase());
if(compare == 0){
if(o1.getFirstName() == null || o1.getFirstName() == null){
return o1.getLastName() == null ? -1 : 1;
}
compare = o1.getFirstName().trim().toUpperCase().compareTo(o2.getFirstName().trim().toUpperCase());
}
return compare;
}
});
for(UserModel userModel : list){
models.add(userModel);
}
}
}
}
return usersCache;
}
public List getModels(String search, long searchRoleId, int searchStatusId) throws Exception {
ConcurrentSkipListSet<UserModel> localSet = models;
if (localSet == null) {
return null;
}
if ((search == null || search.isEmpty()) && searchRoleId < 0 && searchStatusId < 0) {
return Arrays.asList(localSet.toArray());
}
List list = new UserModelList();
Iterator it = localSet.iterator();
if (search == null || search.isEmpty()) {
while (it.hasNext()) {
UserModel user = (UserModel) it.next();
if ((user.getRoleId() == searchRoleId || searchRoleId < 0) &&
(user.getStatus() == searchStatusId || searchStatusId < 0)) {
list.add(user);
}
}
}
else {
search = search.toLowerCase().trim();
Pattern integerPattern = Pattern.compile("^\\d*$");
//integer will search pams id
UserAccountModelList userAccounts = null;
if (integerPattern.matcher(search).matches()) {
userAccounts = UserAccount.getUserAccountsByReference(Source.PAMS.toString(), search);
}
while (it.hasNext()) {
UserModel user = (UserModel) it.next();
//normally this list will be no more than 10 records
if(userAccounts != null) {
for(UserAccountModel userAccount : userAccounts){
if((userAccount.getUserId() == user.getId())
&& (user.getRoleId() == searchRoleId || searchRoleId < 0) &&
(user.getStatus() == searchStatusId || searchStatusId < 0)){
list.add(user);
continue;
}
}
}
String userId = new Long(user.getId()).toString();
if (((userId != null && userId.contains(search)) ||
(user.getEmail() != null && user.getEmail().toLowerCase().contains(search)) ||
(user.getFirstName() != null && user.getFirstName().toLowerCase().contains(search)) ||
(user.getLastName() != null && user.getLastName().toLowerCase().contains(search)) ||
(user.getLoginName() != null && user.getLoginName().toLowerCase().contains(search))
)
&& (user.getRoleId() == searchRoleId || searchRoleId < 0) &&
(user.getStatus() == searchStatusId || searchStatusId < 0))
{
list.add(user);
}
}
}
return list;
}
/*
* this operation will not be heavily used
*/
public UserModel addModel(UserModel user) throws Exception {
if(user == null){
return null;
}
user = User.userCreate(user);
if(user != null){
ConcurrentSkipListSet<UserModel> localSet = models;
localSet.add(user);
}
return user;
}
/*
* this operation will not be heavily used
*/
public UserModel updateModel(UserModel user) throws Exception {
if(user == null){
return null;
}
user = User.userUpdate(user);
put(user);
return user;
}
/*
* Password format:
* [aaabbbn] where:
* aaa = first three characters of client’s first name and
* bbbb = first three characters of client’s surname, and
* n = suffix number – this is only required where the ‘a’ and ‘b’ combination already exists. Starting at 1, continue until a unique combination is found.
* This function is only used in creating a user
*/
public String getLoginName(String firstName, String lastName) {
if(firstName == null || lastName == null
|| firstName.isEmpty() || lastName.isEmpty()) {
return null;
}
if (firstName.length()>3) {
firstName = firstName.substring(0, 3);
}
if (lastName.length()>3) {
lastName = lastName.substring(0, 3);
}
firstName = firstName.toLowerCase();
lastName = lastName.toLowerCase();
String loginName = firstName + lastName;
int length = loginName.length();
for(int i = length; i<6 ; i++) {
loginName = loginName + "1";
}
ConcurrentSkipListSet<UserModel> localSet = models;
int largestId =0;
String matchReg = "^" + loginName + "[0-9]*";
for(UserModel user : localSet) {
if(user.getLoginName() != null && user.getLoginName().toLowerCase().matches(matchReg)) {
int i = Integer.parseInt(user.getLoginName().substring(6));
if (largestId < i) {
largestId = i;
}
}
}
largestId++;
return loginName + largestId;
}
/*
* this operation will not be heavily used
*/
private void put(UserModel wsUser) {
ConcurrentSkipListSet<UserModel> localSet = models;
if(wsUser == null || localSet == null){
return;
}
UserModel cacheUser = null;
for(UserModel user : localSet){
if(user.getId() == wsUser.getId()) {
cacheUser = user;
break;
}
}
synchronized (UserCache.class) {
if(cacheUser != null){
localSet.remove(cacheUser);
}
localSet.add(wsUser);
}
}
/*
* this operation will not be heavily used
*/
public UserModel getUserById(long id) throws Exception {
UserModel wsUser = User.userGet(id);
put(wsUser);
return wsUser;
}
}