面试题答案
一键面试1. 类设计优化
- 单一职责原则:将不同功能拆分到不同类中,如数据库查询操作封装到
UserDao
类,密码验证封装到PasswordVerifier
类,令牌生成封装到TokenGenerator
类。这样每个类职责明确,便于维护和复用。
2. 数据结构选择
- 缓存用户信息:使用
ConcurrentHashMap
缓存已登录用户信息,减少数据库查询次数。ConcurrentHashMap
线程安全,适用于高并发场景。
private static final ConcurrentHashMap<String, User> userCache = new ConcurrentHashMap<>();
3. 线程池使用
- 创建线程池:使用
ThreadPoolExecutor
创建线程池来处理用户登录认证任务,提高线程复用,减少线程创建销毁开销。
private static final ExecutorService executorService = new ThreadPoolExecutor(
10,
100,
60L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1000)
);
- 提交任务:在登录认证方法中,将任务提交到线程池。
public void authenticateUser(User user) {
executorService.submit(() -> {
// 具体认证逻辑
});
}
4. 锁机制优化
- 细粒度锁:对于涉及共享资源的操作,使用
ReentrantLock
并采用细粒度锁策略。例如,在更新用户缓存时,只对缓存操作加锁。
private static final ReentrantLock lock = new ReentrantLock();
public void updateUserCache(User user) {
lock.lock();
try {
userCache.put(user.getUsername(), user);
} finally {
lock.unlock();
}
}
- 读写锁:如果对用户缓存读操作远多于写操作,可以使用
ReentrantReadWriteLock
。读操作时允许多个线程同时进行,写操作时只允许一个线程进行。
private static final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private static final Lock readLock = readWriteLock.readLock();
private static final Lock writeLock = readWriteLock.writeLock();
public User getUserFromCache(String username) {
readLock.lock();
try {
return userCache.get(username);
} finally {
readLock.unlock();
}
}
public void updateUserCache(User user) {
writeLock.lock();
try {
userCache.put(user.getUsername(), user);
} finally {
writeLock.unlock();
}
}
5. 关键代码示例
下面是一个简化的用户登录认证类示例:
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class UserAuthenticator {
private static final ConcurrentHashMap<String, User> userCache = new ConcurrentHashMap<>();
private static final ExecutorService executorService = new ThreadPoolExecutor(
10,
100,
60L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1000)
);
private static final ReentrantLock lock = new ReentrantLock();
public void authenticateUser(User user) {
executorService.submit(() -> {
boolean isValid = PasswordVerifier.verifyPassword(user.getPassword());
if (isValid) {
User dbUser = UserDao.getUserFromDB(user.getUsername());
if (dbUser != null) {
String token = TokenGenerator.generateToken(dbUser);
lock.lock();
try {
userCache.put(dbUser.getUsername(), dbUser);
} finally {
lock.unlock();
}
System.out.println("User authenticated, token: " + token);
}
}
});
}
}
class UserDao {
public User getUserFromDB(String username) {
// 实际数据库查询逻辑
return null;
}
}
class PasswordVerifier {
public static boolean verifyPassword(String password) {
// 实际密码验证逻辑
return true;
}
}
class TokenGenerator {
public static String generateToken(User user) {
// 实际令牌生成逻辑
return "token";
}
}
class User {
private String username;
private String password;
public User(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
}