2 回答
TA贡献1821条经验 获得超6个赞
我想澄清一下这个问题
什么是线程优先级?根据 java SE 文档
每个线程都有一个优先级。具有较高优先级的线程优先于具有较低优先级的线程执行。
即使您创建具有优先级的线程,它也不能完全保证优先级较低的线程首先执行,您可能必须阻塞优先级较低的线程,直到执行其他线程
对于小型 java 程序,您可以自己处理线程执行,但对于较大的程序,建议您使用 vanilla Java 中的 Executor Framework(来自 java.util.concurrent 包)或使用 spring TaskExecutor。通过使用这两个框架,您可以异步执行任务,即作为主任务的一部分在后台执行它们。
对生产的影响:
例如,主要任务将是调用您的其余端点(即/account),并在调用帐户端点时您想要向客户发送欢迎电子邮件,这是第三方 API 调用,可以使用 Executor Framework 或 Spring 异步执行TaskExecutor 异步执行它们,即作为后台进程,它们不会对当前 API 产生影响,但肯定会对生产服务器产生影响,因为您在同一个 JVM 中运行线程并且它们共享公共内存。如果创建了许多线程但没有销毁,那么服务器肯定会崩溃。
因此,使用 Executor Framework 或 Spring TaskExecutor 并不能保证它不会影响您当前的生产,它肯定会提高所调用的其余 API 的性能。因为它是异步执行的并且关于您的其他问题
我可以使用 Executors.newCachedThreadPool()
是的,如果您有许多短期任务,例如更新数据库中的单个列或仅触发一次休息端点,并且它不适合批量加载或执行某些更新 10000 条记录的后端作业,因为它会创建更大的数量每个任务都有多个线程,您肯定会遇到内存问题。
TA贡献1810条经验 获得超4个赞
这是一种创建可配置任务“堆”并始终将主任务保留在堆顶部的方法。
总结这个过程,您应该创建一个自定义任务执行器。首先,您需要创建一个 ThreadPoolTaskExecutor bean,并覆盖一个方法。需要修改的属性有:CorePoolSize(初始线程数)、QueueCapacity(队列中等待的线程数)和MaxPoolSize(最大线程数)。使用这些参数,您可以配置应用程序限制,以使该服务不会影响生产性能。
@Bean("CustomTaskExecutor")
public TaskExecutor threadPoolTaskExecutor(
@Value("${spring.async.core-pool-size}") int corePoolSize,
@Value("${spring.async.max-pool-size}") int maxPoolSize,
@Value("${spring.async.queue-capacity}") int queueCapacity) {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor() {
@Override
protected BlockingQueue<Runnable> createQueue(int queueCapacity) {
return new PriorityBlockingQueue<Runnable>(queueCapacity);
}
};
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
return executor;
}
之后,您需要制定任务执行者可以理解的优先级。为此,我们需要创建两个类: 1) 一个实现 Runnable 接口的自定义类,该类将运行任务 2) 一个扩展 FutureTask 并实现 Comparable 接口的包装类,以便任务执行器可以理解任务的优先级选择逻辑任务
public class Task implements Runnable {
private Consumer<Job> jobConsumer;
private Job job;
public Job getJob() {
return this.job;
}
public Task(Consumer<Job> jobConsumer, Job job) {
this.jobConsumer = jobConsumer;
this.job = job;
}
@Override
public void run() {
this.jobConsumer.accept(job);
}
}
然后你就有了 FutureCustomTask 类:
public class FutureCustomTask extends FutureTask<FutureCustomTask> implements Comparable<FutureCustomTask> {
private Task task;
public FutureCustomTask(Task task) {
super(task, null);
this.task = task;
}
@Override
public int compareTo(FutureCustomTask o) {
return task.getJob().getPriority().compareTo(o.task.getJob().getPriority());
}
}
为了执行任务执行器需要自动装配。然后,您可以创建 Task 对象,将其包装在 FutureCustomTask 中,并将其传递给 TaskExecutor。代码应如下所示:
@Autowired
private TaskExecutor taskExecutor;
@Autowired
private JobBusiness jobBusiness;
...
Task task = new Task(jobBusiness::performSomethingOn, job);
taskExecutor.execute(new FutureCustomTask(task));
添加回答
举报