面试题答案
一键面试实现思路
- 获取系统资源使用情况:利用
com.sun.management.OperatingSystemMXBean
获取CPU利用率和内存使用率。 - 监控任务队列堆积情况:通过
ThreadPoolExecutor
的getQueue().size()
方法获取任务队列当前的任务数量。 - 动态调整线程池大小:根据系统资源和任务队列堆积情况,设定调整策略,动态改变线程池的最大线程数。
关键代码示例
import com.sun.management.OperatingSystemMXBean;
import java.lang.management.ManagementFactory;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class AdaptiveThreadPool {
private static final int CORE_POOL_SIZE = 5;
private static final int MAX_POOL_SIZE = 50;
private static final long KEEP_ALIVE_TIME = 10L;
private static final TimeUnit TIME_UNIT = TimeUnit.SECONDS;
private static final int QUEUE_CAPACITY = 100;
private final ThreadPoolExecutor executor;
private final OperatingSystemMXBean osBean;
public AdaptiveThreadPool() {
BlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>(QUEUE_CAPACITY);
executor = new ThreadPoolExecutor(
CORE_POOL_SIZE,
MAX_POOL_SIZE,
KEEP_ALIVE_TIME,
TIME_UNIT,
taskQueue);
osBean = ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class);
startMonitor();
}
private void startMonitor() {
Thread monitorThread = new Thread(() -> {
while (true) {
try {
double cpuUsage = osBean.getSystemCpuLoad();
long memoryUsage = osBean.getTotalPhysicalMemorySize() - osBean.getFreePhysicalMemorySize();
int queueSize = executor.getQueue().size();
// 调整策略示例:
// 如果CPU利用率低且任务队列堆积,增加线程数
if (cpuUsage < 0.5 && queueSize > QUEUE_CAPACITY * 0.7) {
if (executor.getMaximumPoolSize() < MAX_POOL_SIZE) {
executor.setMaximumPoolSize(executor.getMaximumPoolSize() + 5);
}
}
// 如果CPU利用率高且任务队列无堆积,减少线程数
else if (cpuUsage > 0.8 && queueSize < QUEUE_CAPACITY * 0.3) {
if (executor.getMaximumPoolSize() > CORE_POOL_SIZE) {
executor.setMaximumPoolSize(executor.getMaximumPoolSize() - 5);
}
}
} catch (Exception e) {
e.printStackTrace();
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
monitorThread.setDaemon(true);
monitorThread.start();
}
public void submitTask(Runnable task) {
executor.submit(task);
}
public void shutdown() {
executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
System.err.println("Pool did not terminate");
}
}
} catch (InterruptedException ie) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
使用示例
public class Main {
public static void main(String[] args) {
AdaptiveThreadPool threadPool = new AdaptiveThreadPool();
for (int i = 0; i < 200; i++) {
int taskNumber = i;
threadPool.submitTask(() -> {
System.out.println("Task " + taskNumber + " is running on thread " + Thread.currentThread().getName());
try {
Thread.sleep((long) (Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
threadPool.shutdown();
}
}
上述代码中:
AdaptiveThreadPool
类构造函数初始化线程池,并获取OperatingSystemMXBean
实例。startMonitor
方法启动一个守护线程,定期(每5秒)获取系统资源使用情况和任务队列大小,并根据设定策略调整线程池最大线程数。submitTask
方法用于向线程池提交任务。shutdown
方法用于关闭线程池。
在Main
类中,模拟向线程池提交200个任务,每个任务随机执行一段时间。