设计思路
- 类型安全:通过泛型确保在编译时就明确任务类型,避免运行时类型转换错误。在接口和实现类中严格使用泛型,让编译器进行类型检查。
- 数据竞争:
- 锁机制:采用
java.util.concurrent.locks.Lock
接口及其实现类(如ReentrantLock
)来控制对共享资源的访问。在任务处理涉及共享数据时,在进入处理逻辑前获取锁,处理完后释放锁。
- 线程安全的数据结构:使用
java.util.concurrent
包下的线程安全数据结构,如ConcurrentHashMap
用于存储任务相关数据,ConcurrentLinkedQueue
用于任务队列。这些数据结构内部已经处理了线程安全问题,可避免数据竞争。
- 泛型类型擦除:
- 在泛型接口和实现类中定义方法时,尽量避免在运行时依赖泛型的具体类型。如果确实需要在运行时获取类型信息,可以使用
Class<T>
参数。在实现类构造函数中传入Class<T>
对象,保存该对象用于运行时类型判断。
核心代码框架
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
// 泛型接口
interface TaskExecutor<T> {
void execute(T task);
}
// 具体任务类
class Task {
// 任务相关属性和方法
}
// 具体任务执行类
class SpecificTaskExecutor implements TaskExecutor<Task> {
private final Lock lock = new ReentrantLock();
private final Class<Task> taskClass;
public SpecificTaskExecutor(Class<Task> taskClass) {
this.taskClass = taskClass;
}
@Override
public void execute(Task task) {
lock.lock();
try {
// 任务处理逻辑
if (taskClass.isInstance(task)) {
// 进行任务处理
}
} finally {
lock.unlock();
}
}
}
// 多线程任务调度类
class TaskScheduler {
private final ConcurrentLinkedQueue<Task> taskQueue = new ConcurrentLinkedQueue<>();
private final TaskExecutor<Task> taskExecutor;
public TaskScheduler(TaskExecutor<Task> taskExecutor) {
this.taskExecutor = taskExecutor;
}
public void submitTask(Task task) {
taskQueue.add(task);
}
public void start() {
Thread thread = new Thread(() -> {
while (true) {
Task task = taskQueue.poll();
if (task != null) {
taskExecutor.execute(task);
}
}
});
thread.start();
}
}
使用示例
public class Main {
public static void main(String[] args) {
TaskExecutor<Task> executor = new SpecificTaskExecutor(Task.class);
TaskScheduler scheduler = new TaskScheduler(executor);
scheduler.submitTask(new Task());
scheduler.start();
}
}