面试题答案
一键面试- 任务类设计:
- 定义一个任务类
PrioritizedTask
,实现Comparable
接口,用于在优先级队列中进行比较。
class PrioritizedTask implements Comparable<PrioritizedTask>{ private int priority; private Runnable task; private List<PrioritizedTask> dependencies; public PrioritizedTask(int priority, Runnable task, List<PrioritizedTask> dependencies) { this.priority = priority; this.task = task; this.dependencies = dependencies; } public int getPriority() { return priority; } public Runnable getTask() { return task; } public List<PrioritizedTask> getDependencies() { return dependencies; } @Override public int compareTo(PrioritizedTask other) { return Integer.compare(other.priority, this.priority); } }
- 定义一个任务类
- 优先级队列和线程池:
- 使用
PriorityQueue
来存储任务。 - 创建
ThreadPoolExecutor
线程池,设置合适的核心线程数、最大线程数等参数。
PriorityQueue<PrioritizedTask> taskQueue = new PriorityQueue<>(); ThreadPoolExecutor executor = new ThreadPoolExecutor( 5, 10, 10L, TimeUnit.SECONDS, new LinkedBlockingQueue<>() );
- 使用
- 处理任务依赖:
- 在任务执行前,检查其依赖的任务是否已经完成。可以通过一个
Map<PrioritizedTask, Boolean>
来记录任务是否完成。
Map<PrioritizedTask, Boolean> taskCompletionMap = new HashMap<>();
- 提交任务时,先将任务放入队列,然后检查依赖。如果依赖都已完成,则提交任务到线程池执行;否则等待依赖完成。
public void submitTask(PrioritizedTask task) { taskQueue.add(task); boolean canExecute = true; for (PrioritizedTask dependency : task.getDependencies()) { if (!taskCompletionMap.getOrDefault(dependency, false)) { canExecute = false; break; } } if (canExecute) { executor.submit(() -> { try { task.getTask().run(); taskCompletionMap.put(task, true); checkAndSubmitDependentTasks(task); } catch (Exception e) { e.printStackTrace(); } }); } }
- 任务完成后,检查依赖它的任务是否可以执行,若可以则提交到线程池。
private void checkAndSubmitDependentTasks(PrioritizedTask completedTask) { for (PrioritizedTask task : taskQueue) { if (task.getDependencies().contains(completedTask)) { boolean canExecute = true; for (PrioritizedTask dependency : task.getDependencies()) { if (!taskCompletionMap.getOrDefault(dependency, false)) { canExecute = false; break; } } if (canExecute) { executor.submit(() -> { try { task.getTask().run(); taskCompletionMap.put(task, true); checkAndSubmitDependentTasks(task); } catch (Exception e) { e.printStackTrace(); } }); taskQueue.remove(task); } } } }
- 在任务执行前,检查其依赖的任务是否已经完成。可以通过一个
- 避免死锁:
- 采用资源分配图算法(如死锁检测算法),定期检查任务之间的依赖关系图是否存在环。
- 为任务分配唯一的ID,在添加任务依赖时,先构建依赖关系图,然后检测是否存在环。如果存在环,则抛出异常或采取相应措施(如提示用户任务依赖存在问题)。
- 可以使用深度优先搜索(DFS)算法检测环:
boolean hasCycle(List<PrioritizedTask> tasks) { Map<PrioritizedTask, Boolean> visited = new HashMap<>(); Map<PrioritizedTask, Boolean> recursionStack = new HashMap<>(); for (PrioritizedTask task : tasks) { if (!visited.getOrDefault(task, false)) { if (isCyclic(task, visited, recursionStack)) { return true; } } } return false; } boolean isCyclic(PrioritizedTask task, Map<PrioritizedTask, Boolean> visited, Map<PrioritizedTask, Boolean> recursionStack) { visited.put(task, true); recursionStack.put(task, true); for (PrioritizedTask dependency : task.getDependencies()) { if (!visited.getOrDefault(dependency, false)) { if (isCyclic(dependency, visited, recursionStack)) { return true; } } else if (recursionStack.getOrDefault(dependency, false)) { return true; } } recursionStack.put(task, false); return false; }
- 动态变化的任务优先级:
- 当任务优先级发生变化时,从优先级队列中移除该任务,更新其优先级,然后重新添加到队列中。
public void updateTaskPriority(PrioritizedTask task, int newPriority) { taskQueue.remove(task); task.priority = newPriority; taskQueue.add(task); }
- 可以使用
ScheduledExecutorService
定期检查任务的优先级是否需要调整,根据业务规则进行相应的更新操作。
通过以上方案,可以基于Java优先级队列实现一个高效稳定的线程池任务调度方案,处理任务依赖、避免死锁,并适应动态变化的任务优先级。