面试题答案
一键面试潜在问题分析
- 线程安全问题:
- 原因:策略模式中,策略类可能包含成员变量,如果多个线程同时访问和修改这些成员变量,就会出现线程安全问题。例如,某个策略类中有一个计数器变量用于统计执行次数,多线程并发执行该策略时,计数器的更新可能会出现数据不一致。
- 影响:导致程序运行结果不正确,可能出现数据丢失、重复计算等问题。
- 性能瓶颈问题:
- 原因:在高并发场景下,频繁创建策略对象会消耗大量系统资源,如内存和CPU时间。例如,如果每次请求都创建一个新的策略对象,随着并发量的增加,创建对象的开销会变得很大。另外,如果策略选择逻辑复杂,每次进行策略选择时都需要进行复杂的条件判断,也会影响性能。
- 影响:系统响应时间变长,吞吐量降低,甚至可能导致系统资源耗尽而崩溃。
优化策略
- 针对线程安全问题:
- 不可变对象:将策略类设计为不可变类,即没有可修改的成员变量。这样,多个线程可以安全地共享同一个策略对象实例。
- 线程局部变量:如果策略类必须有状态,可以使用
ThreadLocal
来存储线程特定的状态,避免多线程之间的状态干扰。
- 针对性能瓶颈问题:
- 对象池:使用对象池技术来复用策略对象,避免频繁创建和销毁对象。可以使用第三方库如Apache Commons Pool来实现对象池。
- 优化策略选择逻辑:通过使用更高效的数据结构(如
Map
)来存储策略映射关系,减少策略选择时的条件判断时间。
具体代码实现方式
- 线程安全的策略模式实现(以不可变对象为例):
// 定义策略接口
interface Strategy {
void execute();
}
// 具体策略类,设计为不可变类
class ConcreteStrategyA implements Strategy {
@Override
public void execute() {
System.out.println("执行策略A");
}
}
class ConcreteStrategyB implements Strategy {
@Override
public void execute() {
System.out.println("执行策略B");
}
}
// 上下文类
class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void executeStrategy() {
strategy.execute();
}
}
在高并发场景下,可以预先创建好策略对象实例,并在多个线程间共享:
public class Main {
private static final Strategy strategyA = new ConcreteStrategyA();
private static final Strategy strategyB = new ConcreteStrategyB();
public static void main(String[] args) {
// 模拟高并发
for (int i = 0; i < 10; i++) {
new Thread(() -> {
Context context = new Context(strategyA);
context.executeStrategy();
}).start();
new Thread(() -> {
Context context = new Context(strategyB);
context.executeStrategy();
}).start();
}
}
}
- 使用对象池优化性能:
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
// 定义策略接口
interface Strategy {
void execute();
}
// 具体策略类
class ConcreteStrategyA implements Strategy {
@Override
public void execute() {
System.out.println("执行策略A");
}
}
// 策略对象工厂
class StrategyFactory extends BasePooledObjectFactory<Strategy> {
@Override
public Strategy create() throws Exception {
return new ConcreteStrategyA();
}
@Override
public PooledObject<Strategy> wrap(Strategy strategy) {
return new DefaultPooledObject<>(strategy);
}
}
// 上下文类
class Context {
private GenericObjectPool<Strategy> pool;
public Context(GenericObjectPool<Strategy> pool) {
this.pool = pool;
}
public void executeStrategy() {
Strategy strategy = null;
try {
strategy = pool.borrowObject();
strategy.execute();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (strategy != null) {
pool.returnObject(strategy);
}
}
}
}
在应用启动时初始化对象池:
public class Main {
public static void main(String[] args) {
GenericObjectPoolConfig<Strategy> config = new GenericObjectPoolConfig<>();
config.setMaxTotal(10);
StrategyFactory factory = new StrategyFactory();
GenericObjectPool<Strategy> pool = new GenericObjectPool<>(factory, config);
// 模拟高并发
for (int i = 0; i < 10; i++) {
new Thread(() -> {
Context context = new Context(pool);
context.executeStrategy();
}).start();
}
}
}
- 优化策略选择逻辑:
// 定义策略接口
interface Strategy {
void execute();
}
// 具体策略类
class ConcreteStrategyA implements Strategy {
@Override
public void execute() {
System.out.println("执行策略A");
}
}
class ConcreteStrategyB implements Strategy {
@Override
public void execute() {
System.out.println("执行策略B");
}
}
// 上下文类
class Context {
private Strategy strategy;
private static final Map<String, Strategy> strategyMap = new HashMap<>();
static {
strategyMap.put("A", new ConcreteStrategyA());
strategyMap.put("B", new ConcreteStrategyB());
}
public Context(String strategyKey) {
this.strategy = strategyMap.get(strategyKey);
}
public void executeStrategy() {
if (strategy != null) {
strategy.execute();
}
}
}
在高并发场景下使用:
public class Main {
public static void main(String[] args) {
// 模拟高并发
for (int i = 0; i < 10; i++) {
new Thread(() -> {
Context context = new Context("A");
context.executeStrategy();
}).start();
new Thread(() -> {
Context context = new Context("B");
context.executeStrategy();
}).start();
}
}
}
策略模式提升系统稳定性和可扩展性的方式
- 稳定性:
- 通过解决线程安全问题,确保系统在多线程环境下运行结果的正确性,避免因数据不一致导致的程序崩溃或错误。
- 优化性能瓶颈,减少系统资源的过度消耗,使系统在高并发压力下仍能保持稳定运行。
- 可扩展性:
- 策略模式的结构使得新增策略非常方便,只需实现策略接口并添加到策略选择逻辑中即可。例如,当系统需要新增一种策略时,只需要创建一个新的实现类,然后在
strategyMap
中添加映射关系,而不需要修改大量现有代码。 - 策略的复用性高,不同的上下文可以复用相同的策略,提高了代码的可维护性和可扩展性。
- 策略模式的结构使得新增策略非常方便,只需实现策略接口并添加到策略选择逻辑中即可。例如,当系统需要新增一种策略时,只需要创建一个新的实现类,然后在