1

I am trying to Tune a thread which does the following:

A thread pool with just 1 thread [CorePoolSize =0, maxPoolSize = 1]

The Queue used is a ArrayBlockingQueue

Quesize = 20

BackGround:
The thread tries to read a request and perform an operation on it.

HOWEVER, eventually the requests have increased so much that the thread is always busy and consume 1 CPU which makes it a resource hog.

What I want to do it , instead sample the requests at intervals and process them . Other requests can be safely ignored.

What I would have to do is put a sleep in "operation" function so that for each task the thread sleeps for sometime and releases the CPU.

Quesiton:
However , I was wondering if there is a way to use a queue which basically itself sleeps for sometime before it reads the next element. This would be ideal since sleeping a task in the middle of execution and keeping the execution incomplete just doesn't sound the best to me.

Please let me know if you have any other suggestions as well for the tasks

Thanks.

Edit: I have added a follow-up question here corrected the maxpool size to be 1 [written in a haste] .. thanks tim for pointing it out.

Community
  • 1
  • 1
codeObserver
  • 6,521
  • 16
  • 76
  • 121
  • 1
    It's not really a "resource hog" is there is that much work to do. Do you really want to artificially slow down requests? Why are requests (clients?) being sent faster than they can be processed? This is not sustainable. – AngerClown Oct 05 '10 at 00:19
  • Good point. If the clients are making a lot of requests that are rejected because of a full queue, they are wasting CPU that could have been balanced better between the clients and the executor. The queue is a buffer to "smooth out" the load over time; rejects should be rare, not routine. – erickson Oct 05 '10 at 00:27
  • The client is not a dedicated client of the requester in the real sense. The requester has a dedicated client which scales up as per the number of requests. The client I am working is like an extra one for logging , monitoring types of operation ..hence sampling is still fine to get the picture on requests .. hope that makes sense. – codeObserver Oct 05 '10 at 00:55
  • @p1, your maxPoolSize can not be 0, that violates an invariant enforced in the constructor of a ThreadPoolExecutor. Please update your question with the correct value you are using, or the exact method of construction you are using if you are not sure. – Tim Bender Oct 07 '10 at 19:56

4 Answers4

1

No, you can't make the thread sleep while it's in the pool. If there's a task in the queue, it will be executed.

Pausing within a queued task is the only way to force the thread to be idle in spite of queued tasks. Now, the "sleep" doesn't have to be in the same task as the "work"—you could queue a separate rest task after each real task, which might make for a cleaner implementation. More importantly, if the work is a Callable that returns a result, separating into two tasks will allow you to obtain the result as soon as possible.

As a refinement, rather than sleeping for a fixed interval between every task, you could "throttle" execution to a specified rate. This would allow you to avoid waiting unnecessarily between tasks, yet avoid executing too many tasks within a specified time interval. You can read another answer of mine for a simple way to implement this with a DelayQueue.

Community
  • 1
  • 1
erickson
  • 265,237
  • 58
  • 395
  • 493
1

You could subclass ThreadPool and override beforeExecute to sleep for some time:

@Overrides
protected void beforeExecute(Thread t,
                         Runnable r){
    try{
       Thread.sleep( millis);  // will sleep the correct thread, see JavaDoc
    }
    catch (InterruptedException e){}

  }

But see AngerClown's comment about artificially slowing down the queue probably not being a good idea.

Thilo
  • 257,207
  • 101
  • 511
  • 656
  • Thanks, Thilo .. I think beforeExecute might do the trick . Will make the changes and accept the answer if it works fine :). Keeping the thread open in case there are few more ideas :) – codeObserver Oct 05 '10 at 20:57
  • +1 for mentioning the beforeExecute method. People are sometimes so obsessed with the ExecutorService abstraction that they tend to forget the ThreadPoolExecutor implementation has some neat offerings too. – Tim Bender Oct 05 '10 at 22:52
  • I tried tinkering with this approach. Interestingly, @times the beforeExecute() is invoked and then immediately the task is executed without sleeping and then after the sleep time has elapsed the task is re-executed. I am using a thread pool and there is just one thread [see details in my question] .. am I missing something ?? – codeObserver Oct 06 '10 at 23:04
1

This might not work for you, but you could try setting the executor's thread priority to low.

Essentially, create the ThreadPoolExecutor with a custom ThreadFactory. Have the ThreadFactory.newThread() method return Threads with a priority of Thread.MIN_PRIORITY. This will cause the executor service you use to only be scheduled if there is an available core to run it.

The implication: On a system that strictly uses time slicing, you will only be given a time slice to execute if there is no other Thread in the entire program with a greater priority asking to be scheduled. Depending on how busy your application really is, you might get scheduled every once in awhile, or you might not be scheduled at all.

Tim Bender
  • 20,112
  • 2
  • 49
  • 58
  • thanks .. I had considered this approach but I am afraid that it might starve my thread. Also, my thread is trying to sample data so I want a real world picture of what is happening ... doing this might skew the sample to only those periods where the CPU is low ...which defeats the purpose of having the thread. Also the individual task performed by thread is very small [but there are too many tasks] .. so I think sleeping might work better. Agreed ? – codeObserver Oct 05 '10 at 23:32
  • Yes, agreed. I think Thilo's solution is best, which is why I up voted it. – Tim Bender Oct 06 '10 at 00:00
1

The reason the thread is consuming 100% CPU is because it is given more work than it can process. Adding a delay between tasks is not going to fix this problem. It is just make things worse.

Instead you should look at WHY your tasks are consuming so much CPU e.g. with a profiler and change them so that consume less CPU until you find that your thread can keep up and it no longer consumes 100% cpu.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • this is the obvious answer... it is like facebook being too busy, and delaying logins to prevent people use the web. – Javier Loureiro Dec 25 '10 at 22:28
  • @Javier, facebook has little control over the rate at which requests come in. Some people try to overload the servers deliberately to see what happens. Your code might assume the work load is "friendlier" – Peter Lawrey Dec 26 '10 at 08:23