使用Spring / Spring-Batch实现同步可重复任务的更好方法

时间:2015-01-20 08:40:50

标签: java multithreading spring asynchronous spring-batch

我需要轮询数据库以获取特定结果。我无法在我的代码中继续,直到我得到预期的结果(除了传递超时间隔的情况)

步骤A - > Steb B - >第C步

这样做的简单方法(但对我来说不合适)是:

numOfRetry=0;
invokeStepA();

while(true)
{
   numOfRetry++
   boolen result=invokeStepB();
   if(result || numOfRetry==3)
   {
      break;
   }
    else
   {
      Thread.sleep(100000)
    }
invokeStepC();
  • 假设数据库轮询正在步骤B中进行。

在调用这些作业的时候,在我的Spring bean服务上使用while循环时感觉不对。

也许我可以更好地实现这一点?

谢谢。

关于我的流程的进一步解释:

步骤A是调用外部服务来做一些逻辑。

步骤B需要轮询另一项服务,检查步骤A是否完成了它的工作(如果已完成,我可以继续执行StepC,否则我需要在X秒内重试并再次检查)

StepC - 必须在StepB返回true后才能完成的另一个逻辑。

  • 步骤A所做的逻辑发生在外部服务上。

2 个答案:

答案 0 :(得分:0)

asynchronous方式发生

int count = Runtime.getRuntime().availableProcessors();
ExecutorService threadPool = Executors.newFixedThreadPool(count);

invokeStepA();
for (int i = 0; i < RETRY_COUNT; i++) {
    Future f = threadPool.submit(new Callable() {
        @Override
        public Object call() {
            return invokeStepB();
        }
    }

    result = (YOUR_DATA_STRUCTURE) f.get();
    if (resultIsOK(result)) {
        break;
    }
}

但是,我认为既然您的任务是有序的,并且假设您不能去做其他事情,那么使用asynchronous并不是那么有效。如果您有特殊要求,请告诉我有关您背景的更多信息。

编辑:我认为您的新要求看起来需要一种正确的方法来判断步骤A是否已经完成。因此,您可以使用CountDownLatch检查A是否已正确完成。即

private final int count = Runtime.getRuntime().availableProcessors();
private final ExecutorService threadPool = Executors.newFixedThreadPool(count);

// invoke step A
invokeStepA();

// submit step B
final CountDownLatch latch = new CountDownLatch(1);
threadPool.submit(new Runnable() {
    @Override
    public void run() {
        invokeStepB();
        latch.countDown();
    }
});

// wait for step B
boolean result;
try {
    result = latch.await(TIME_OUT_IN_MILLISECONDS, TimeUnit.MILLISECOND);
} catch (InterruptedException e) {
}

// Check result
if (result) {
    invokeStepC();
} else {
    LOG.error("Timeout waiting for step A.");
}

这假定您的invokeStepA()是阻止方法。

答案 1 :(得分:0)

以下是使用事件驱动方法的另一个想法。这只是我的想法,没有经过测试;)

import org.springframework.context.ApplicationEventPublisher;

@Service
public class JobA {

  @Autowired
  private ApplicationEventPublisher applicationEventPublisher;

  @Scheduled(cron = "0 0 * * * ?")
  public void doStepA() {
    log.debug("some heavy lifting");
    Object someData = ....;
    applicationEventPublisher.publishEvent(new JobAEvent("Jo, I'm finished", someData));
  }      

}

@Service
public class JobB implements ApplicationListener<JobAEvent> {

  @Autowired
  private ApplicationEventPublisher applicationEventPublisher;

  @Override
  public void onApplicationEvent(final JobAEvent event) {
    log.debug("do something more based on the event data"); 
    Object someMoreData = ....;
    applicationEventPublisher.publishEvent(new JobBEvent("Dude, me too", event.getSomeData(), someMoreData));
  }

}

@Service
public class JobC implements ApplicationListener<JobBEvent> {

  @Autowired
  private ApplicationEventPublisher applicationEventPublisher;

  @Override
  public void onApplicationEvent(final JobBEvent event) {
    log.debug("do even more work");
  }

}

编辑: 您也可以直接调用该方法,然后同步运行。另一种可能性是使用&#39; @Async&#39;