0

There is a producer keeps generating files and put them into a special path. The consumer is a using WatchService to monitor the path and pick up any new generated files to work. Usually, the consumer's speed is slower than producer. In rare case, if the consumer finishes all the existing tasks and there is nothing new in the path yet, the consumer needs to hold on for a while.

while(true) {
    // do something...
    if(condition) {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            // handler
        }
    }
}

IDE is complaining that calling to Thread.sleep() in a while loop are indicative of "busy-waiting". Busy-waiting is often inefficient, and may result in unexpected deadlocks as busy-waiting threads do not release locked resources. Ignore this IDE warning will be my last option.

How could I change my code to avoid the above warning architecture wise?

(It seems a scheduled thread pool won't meet my requirement. Please correct me if I'm wrong.)

Thanks for your comments and answers. Buffer events from WatchService to a blocking queue will work.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Top.Deck
  • 1,077
  • 3
  • 16
  • 31
  • 1
    That is an IDE warning, not a compiler warning. Ignore it. – f1sh Jul 03 '20 at 13:04
  • either ignore it, or use a scheduler – jhamon Jul 03 '20 at 13:08
  • 2
    That *sort of* looks like a [Semaphore](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Semaphore.html) (if you look at it from afar and squint your eyes), except it waits for a predetermined time. – Kayaman Jul 03 '20 at 13:13
  • I wouldn't sleep. Check out my answer here https://stackoverflow.com/questions/62293246/java-asynchronously-call-a-method-for-target-output/62323465#62323465 and see if you can use something like that. – Dan M Jul 03 '20 at 13:15
  • @Kayaman I thought about Semaphore, but not sure how to use it here. Please see my updated question. – Top.Deck Jul 03 '20 at 13:31
  • What type of queue are you using? Some of Java's `Queue` implementations have blocking `poll()` methods. – Sean Bright Jul 03 '20 at 13:32
  • @SeanBright it's not a queue exactly.. Sry for the confusion. Updated question. – Top.Deck Jul 03 '20 at 13:35
  • 1
    Use a [WatchService](https://docs.oracle.com/javase/tutorial/essential/io/notification.html) to detect filesystem events and queue these events into a [BlockingQueue](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/BlockingQueue.html) implementation, for example an [ArrayBlockingQueue](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ArrayBlockingQueue.html) of sufficient size. – predi Jul 03 '20 at 13:48
  • @predi yes it works. thx~ – Top.Deck Jul 03 '20 at 13:57
  • Does this answer your question? [How to wait indefinitely in Java?](https://stackoverflow.com/questions/62616813/how-to-wait-indefinitely-in-java) – andreoss Jul 03 '20 at 16:32

2 Answers2

1

I completely agree with the IDE. If you use Thread.sleep() you are wrong, most of the time. If you don't know why, then you are wrong all of the time. Yeah I know, it's a strong statement, but in my opinion it should always been kept in mind: in the best case "wrong" means "sub-optimal", in worst cases "wrong" can mean "bad architecture".

In your case, a solution is to use a blocking queue that sends consumer to sleep when the queue is empty and wakes up sleeping consumers when some element arrives.

By the way, I also believe you have the same issue when the queue is full: you may want to pause the producer.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Jack
  • 1,488
  • 11
  • 21
  • Totally agree with you that Thred.sleep() here is a bad architecture. The challenge here is, it's not exactly a queue. The producer is actually downloading a bunch of files. The consumer is using WatchService to monitor files in a the path and work on new files. Will update the question. – Top.Deck Jul 03 '20 at 13:46
  • Regardless what they are doing, you will have a producer that "write" to a consumer, and a consumer that "read" from it. Make these calls blocking: write must block the producer if the buffer is full (or no consumers are available when no buffer is in place) and read must block the consumer if there are no elements available to read. – Jack Jul 03 '20 at 13:50
-3

Using Thread.sleep in a real time application is not recommended at all. For your requirement it is recommended to use a scheduler to check up on the path once in a while based on the your application traffic. Any cron job would also help.

SAS DEV
  • 70
  • 3