面试题答案
一键面试1. 使用Future模式设计框架处理异步任务
1.1 定义任务接口
首先定义一个接口,用于表示异步任务。
public interface Task<V> {
V execute();
}
1.2 定义Future接口
这个接口用于获取异步任务的执行结果。
public interface Future<V> {
V get() throws InterruptedException;
boolean isDone();
}
1.3 定义FutureTask类
实现Task
和Future
接口,用于管理异步任务的执行和结果获取。
public class FutureTask<V> implements Task<V>, Future<V> {
private V result;
private boolean isCompleted = false;
private final Task<V> task;
public FutureTask(Task<V> task) {
this.task = task;
}
@Override
public V execute() {
try {
result = task.execute();
} finally {
isCompleted = true;
}
return result;
}
@Override
public V get() throws InterruptedException {
while (!isCompleted) {
Thread.sleep(100);
}
return result;
}
@Override
public boolean isDone() {
return isCompleted;
}
}
1.4 定义线程池和任务调度
使用线程池来执行异步任务。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TaskExecutor {
private static final ExecutorService executor = Executors.newFixedThreadPool(10);
public static <V> Future<V> submit(Task<V> task) {
FutureTask<V> futureTask = new FutureTask<>(task);
executor.submit(futureTask);
return futureTask;
}
public static void shutdown() {
executor.shutdown();
}
}
2. 实现扩展性
2.1 动态线程池大小调整
为了应对任务数量动态增长的情况,可以使用ThreadPoolExecutor
并动态调整线程池的核心线程数和最大线程数。
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class DynamicTaskExecutor {
private static final BlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>();
private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, // 核心线程数
20, // 最大线程数
10, TimeUnit.SECONDS,
taskQueue);
public static <V> Future<V> submit(Task<V> task) {
FutureTask<V> futureTask = new FutureTask<>(task);
executor.submit(futureTask);
return futureTask;
}
public static void adjustThreadPoolSize(int corePoolSize, int maximumPoolSize) {
executor.setCorePoolSize(corePoolSize);
executor.setMaximumPoolSize(maximumPoolSize);
}
public static void shutdown() {
executor.shutdown();
}
}
通过adjustThreadPoolSize
方法,可以根据任务的负载情况动态调整线程池的大小,以适应任务数量的动态增长。
2.2 任务队列扩展
使用可扩展的任务队列,例如LinkedBlockingQueue
,其默认容量为Integer.MAX_VALUE
,可以容纳大量任务。如果需要更精细的控制,可以根据业务需求设置合适的容量,并在任务队列接近满时采取相应的策略,如拒绝策略或者动态扩展队列容量。
2.3 分布式任务处理
对于极高并发的场景,可以引入分布式任务处理框架,如Apache Kafka、RabbitMQ等,将任务分发到多个节点进行处理,从而进一步提升系统的扩展性。通过消息队列,系统可以解耦任务的提交和执行,并且可以方便地增加或减少处理节点来应对任务数量的变化。