相关文章推荐
谦和的弓箭  ·  解决 Maven 报错 ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I am working on a system where I need a while(true) where the loop constantly listens to a queue and increments counts in memory.

The data is constantly coming in the queue, so I cannot avoid a while(true) condition. But naturally it increases my CPU utilization to 100%.

So, how can I keep a thread alive which listens to the tail of queue and performs some action, but at the same time reduce the CPU utilization to 100%?

while (true) {} takes lot of cpu because of the while loop. while (true) { /* lot of processing */ } takes lot of cpu because of what is happening in the body. Different problems. Miserable Variable Feb 7, 2013 at 23:59 If it's coming in on a queue, wait for the next element to arrive, using a blocking queue. Hot Licks Feb 7, 2013 at 23:59 Question: " My poor constantly-polling design requires that I use 100% of the CPU. How can I not use 100% of the CPU? " Answer: "Change your design. Don't constantly poll." Nik Bougalis Feb 8, 2013 at 0:17 @Nik I agree, need to rethink the way I am processing a constant stream of data coming in via a queue. zengr Feb 8, 2013 at 0:36 But how can I use BlockingQueue here? I have a persistent queue implementation built over hsqldb. I receive() messages off the persistent queue. So, my while loop keeps polling the queue. zengr Feb 8, 2013 at 0:07 @zengr: We'd have to see your code. The idea is to wait for something to happen, not to constantly check if it has already happened. You just keep checking the queue over and over as fast as you can, which maxes out resources. David Schwartz Feb 8, 2013 at 0:11 If you're polling a database looking for changes (without knowing more about what you're doing - bad idea for a "queue") then you're going to have to sleep() and not continuously poll. Brian Roach Feb 8, 2013 at 0:12 @Brian Roach Well yeah, I agree. But hsqldb behaves a little differently. It has the data in memory and maintains log using which it reconstructs the data in case of a process restart. So, I am polling of a db yes, but the "selects" are in memory. Which is not that bad. zengr Feb 8, 2013 at 0:16 @zengr: It's worse with the data in memory. If it had to access a database over the network, that would at least slow it down and reduce its resource consumption because it would be waiting for a response from the database at least some of time. Since it's all in memory, it's never waiting for anything, just burning resources at the maximum conceivable speed. David Schwartz Feb 8, 2013 at 7:34

LinkedBlockingQueue.take() is what you should be using. This waits for an entry to arrive on the queue, with no additional synchronization mechanism needed.

(There are one or two other blocking queues in Java, IIRC, but they have features that make them unsuitable in the general case. Don't know why such an important mechanism is buried so deeply in arcane classes.)

Based on your comments on another answer, you want to have a queue that is based on changes in hsqldb

Some quick googling turns up:

http://hsqldb.org/doc/guide/triggers-chapt.html

It appears you can set it up so that changes cause a trigger to occur, which will notify a class you write implementing the org.hsqldb.Trigger interface. Have that class contain a reference to a LinkedBlockingDequeue from the Concurrent package in Java and have the trigger add the change to the queue.

You now have a blocking queue that your reading thread will block on until hsqldb fires a trigger (from an update by a writer) which will put something in the queue. The waiting thread will then unblock and have the item off the queue.

+1 for DB trigger. I'm not familiar with that DB, but this is the best answer if it is supported. Martin James Feb 8, 2013 at 0:35 @zengr - Yep, that will work. In the case of no data being there you're only going to "waste" something in the sub-millisecond range in terms of CPU utilization more than likely. If your requirements allow for data to be 10 seconds old then that's absolutely fine. Brian Roach Feb 8, 2013 at 1:47

lbalazscs and Brain have excellent answers. I couldn’t share my code it was hard for them to give them the exact fix for my issue. And having a while(true) which constantly polls a queue is surely the wrong way to go about it. So, here is what I did:

  • I used ScheduledExecutorService with a 10sec delay.
  • I read a block of messages (say 10k) and process those messages
  • thread is invoked again and the "loop" continues.
  • This considerably reduces my CPU usage. Suggestions welcomed.

    Lots of dumb answers from people who read books and only wasted time in schools, not as many direct logic or answers I see.

    while(true) will set your program to use all the CPU power that's basically 'alloted' to it by the windows algorithms to run what is in the loop, usually as-fast-as-possible over and over. This doesn't mean if it says 100% on your application, that if you run a game, your empty loop .exe will be taking all your OS CPU power, the game should still run as intended. It is more like a visual bug, similar to the windows idle process and some other processes. The fix is to add a Sleep(1) (at least 1 millisecond) or better yet a Sleep(5) to make sure other stuff can run and ensure the CPU is not constantly looping your while(true) as fast as possible. This will generally drop CPU usage to 0% or 1% in the visual queue as 1 full millisecond is a big resting time for even older CPU.

    Many times while(trues) or generic endless loops are bad designs and can be drastically slowed down to even Sleep(1000) - 1 second interval checks or higher. Endless loops are not always bad designs, but usually they can be improved..

    funny to see this bug I learned whe nI was like 12 learning C pop up and all the 'dumb' answers given.

    Just know if you try it, unless the scripted slower language you have learned to use has fixed it somewhere along the line by itself, windows will claim to use a lot of CPU on doing an empty loop when the OS is actually having free resources to spend.

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question . Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers .