Почему мои запланированные задания выполняются не параллельно

119
13

Я пытаюсь понять, почему мои запланированные задания выполняются не параллельно. Может быть, что-то не так с моим управлением транзакциями? Метод JobScheduledExecutionService.execute() - это @Scheduled с fixedRate=250, поэтому его нужно запускать каждые 250 мс независимо от того, закончилось ли предыдущее задание. Из-за журналов он работает не так, как ожидалось.

Журналы: https://pastebin.com/M6FaXpeE

Мой код ниже.

@Service
@Slf4j
public class JobExecutionService {

private final TransactionalJobExecutionService transactionalJobExecutionService;

@Autowired
public JobExecutionService(TransactionalJobExecutionService transactionalJobExecutionService) {
this.transactionalJobExecutionService = transactionalJobExecutionService;
}

public void execute() {
TestJob job = transactionalJobExecutionService.getJob();
executeJob(job);
transactionalJobExecutionService.finishJob(job);
}

private void executeJob(TestJob testJob) {
log.debug("Execution-0: {}", testJob.toString());
Random random = new Random();
try {
Thread.sleep(random.nextInt(3000) + 200);
} catch (InterruptedException e) {
log.error("Error", e);
}
log.debug("Execution-1: {}", testJob.toString());
}

}

@Service
@Slf4j
public class JobScheduledExecutionService {

private final JobExecutionService jobExecutionService;

@Autowired
public JobScheduledExecutionService(JobExecutionService jobExecutionService) {
this.jobExecutionService = jobExecutionService;
}

@Scheduled(fixedRate = 250)
public void execute() {
log.trace("Job fired");
jobExecutionService.execute();
}

}

@Service
@Slf4j
@Transactional
public class TransactionalJobExecutionService {

private final Environment environment;
private final TestJobRepository testJobRepository;
private final TestJobResultRepository testJobResultRepository;

@Autowired
public TransactionalJobExecutionService(Environment environment, TestJobRepository testJobRepository, TestJobResultRepository testJobResultRepository) {
this.environment = environment;
this.testJobRepository = testJobRepository;
this.testJobResultRepository = testJobResultRepository;
}

public TestJob getJob() {
TestJob testJob = testJobRepository.findFirstByStatusOrderByIdAsc(
0
);
testJob.setStatus(1);
testJobRepository.save(testJob);
return testJob;
}

public void finishJob(TestJob testJob) {
testJobResultRepository.save(
new TestJobResult(
null,
testJob.getId(),
environment.getProperty("local.server.port")
)
);
}

}

@Configuration
public class SchedulingConfigurerConfiguration implements SchedulingConfigurer {

@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(32);
taskScheduler.initialize();
taskRegistrar.setTaskScheduler(taskScheduler);
}

}

спросил(а) 2017-05-03T22:28:00+03:00 3 года, 8 месяцев назад
1
Решение
73

Причина заключается в том, что планировщик будет запускать только одно событие, которое будет выполняться одним потоком, а затем я не вижу, что вы создаете несколько потоков в своей логике для параллельного выполнения. Этот вызов jobExecutionService.execute(); в execute() из JobScheduledExecutionService находится в одном потоке. Таким образом, в целом это заканчивается последовательным исполнением.

Кажется, вам нужно поставить многопоточную логику [Callable-Future based] в JobExecutionService: execute(), чтобы выбрать job [transactionalJobExecutionService.getJob()] и вызвать executeJob() внутри него. надеюсь это поможет..

ответил(а) 2017-05-04T08:11:00+03:00 3 года, 8 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема