在java中创建无限循环的最佳方法是什么?

时间:2016-12-06 17:26:38

标签: java multithreading loops

我有一个需要无限循环才能保持运行的程序。这样做的原因是我有一个SQS消费者,它将为每个消息分离一个线程,这就是我的大部分逻辑。 可悲的是,SQS消费者在另一个我无法控制的线程上内部运行,因为最好的实现是在主线程上运行它。

我需要一种方法来阻止程序在消费者活着时退出,目前我正在使用带有线程休眠的while循环,但我记得有些事情不是一个非常好的解决方案。

在给定限制我无法更改SQSConsumer的情况下,保持程序活着的最佳方法是什么。

更新:该程序无意停止,SQSConsumer将启动10个从服务中提取消息的线程,我希望它继续执行此操作,直到我强制程序退出将consumer.isRunning()设置为false,或强制程序以Ctrl + c终止。

示例:

SQSConsumer consumer = new SQSConsumer((event) -> {
    callSomeLogicHere(event);
});
while (consumer.isRunning()) {
    Thread.sleep(100);
}

1 个答案:

答案 0 :(得分:3)

使用CountdownLatch

  • 在调用使用者之前创建最终(或有效最终)变量:

    CountdownLatch latch = new CountdownLatch(1);
    
  • 在你的lambda中,用try / finally:

    包围对其他逻辑的调用
    try {
      callSomeOtherLogic();
    } finally {
      latch.countDown();
    }
    
  • 之后,如果您想等待消费者完成,请等待锁定:

    latch.await();
    

请注意,这不是“最好”的方式,因为很少有客观的最佳方法;对于特定的应用程序,只有最好的。

据说,这比更好而不是轮询,因为你不必继续检查另一个线程是否已经完成。如果你每100ms检查一次完成,而另一个线程需要至少10分钟才能完成,那就浪费了大量的时间;你可以使用你的CPU做更有价值的工作。您可以增加睡眠时间以减少检查频率,但是然后增加完成和检测它的过程之间的预期额外等待时间(预期的额外等待时间是睡眠持续时间的一半)。

还应该注意,这假设lambda的完成表明消费者已完成。这可能不是真的:

  • 这种方法假设lambda只执行一次。这种假设可能不正确,例如,如果lambda被执行多次,或者可能永远不执行。
  • 即使只执行一次,消费者也可能会做更多工作;在锁定计数结束后,你可能需要等待一段时间(甚至还要完成轮询)。

简而言之,对于这种情况,这不一定是最好的,甚至是正确的方法。但是,有一整套并发实用程序 - java.util.concurrent - 提供比简单轮询更好的功能,其中一些可能适用于这种情况。