设计思路
- 定义Task类:包含
id
、priority
和status
属性,实现Comparable
接口,根据priority
降序、priority
相同则id
升序排列。
- 使用ConcurrentSkipListSet:用于存储
Task
对象,利用其有序性和线程安全特性。
- 任务状态更新:通过监听
status
变化,当变为“已完成”时从集合中移除。可以采用观察者模式或在setStatus
方法中直接处理。
核心代码实现
import java.util.concurrent.ConcurrentSkipListSet;
// 定义任务状态枚举
enum TaskStatus {
NOT_STARTED, IN_PROGRESS, COMPLETED
}
// 定义Task类
class Task implements Comparable<Task> {
private int id;
private int priority;
private TaskStatus status;
public Task(int id, int priority, TaskStatus status) {
this.id = id;
this.priority = priority;
this.status = status;
}
public int getId() {
return id;
}
public int getPriority() {
return priority;
}
public TaskStatus getStatus() {
return status;
}
public void setStatus(TaskStatus status) {
this.status = status;
if (status == TaskStatus.COMPLETED) {
// 这里可以通过其他方式通知移除,这里简单示意
TaskManager.removeTask(this);
}
}
@Override
public int compareTo(Task other) {
if (this.priority != other.priority) {
return other.priority - this.priority;
} else {
return this.id - other.id;
}
}
}
// 任务管理器类
class TaskManager {
private static final ConcurrentSkipListSet<Task> taskSet = new ConcurrentSkipListSet<>();
public static void addTask(Task task) {
taskSet.add(task);
}
public static void removeTask(Task task) {
taskSet.remove(task);
}
public static ConcurrentSkipListSet<Task> getTaskSet() {
return taskSet;
}
}
可能出现的并发问题及解决方案
- 并发修改问题:虽然
ConcurrentSkipListSet
本身是线程安全的,但在更新任务状态时可能出现多个线程同时尝试移除任务的情况。
- 解决方案:
ConcurrentSkipListSet
的remove
方法本身是线程安全的,所以无需额外同步措施。但如果采用更复杂的通知机制(如观察者模式),在通知和移除任务时要确保线程安全。
- 内存一致性问题:不同线程对任务状态更新的可见性可能存在问题。
- 解决方案:对
status
属性使用volatile
关键字修饰,确保线程对status
的修改能及时被其他线程看到。如在Task
类中private volatile TaskStatus status;
。