Topic
  • 5 replies
  • Latest Post - ‏2005-03-31T16:50:08Z by SystemAdmin
SystemAdmin
SystemAdmin
1240 Posts

Pinned topic Problem with Threadpool and Java 1.5

‏2005-03-18T03:23:54Z |
I'm having a problem with ThreadPools using Java 1.5. I get an intermittant RejectedExecutionException when executing my task. I've gotten it down to a very simple test case. I am defining a fixed size thread pool and also calling prestartAllCoreThreads(). This seems to be the key. If I don't call prestartAllCoreThreads(), it appears to work. Here is the exception followed by the code.
Thanks for any help.....Peter

code
Exception in thread "main" java.util.concurrent.RejectedExecutionException
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoo lExecutor.java:1477)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:384)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:867)
at com.technicacorp.activenode.ee.ThreadTest.start(ThreadTest.java:42)
at com.technicacorp.activenode.ee.ThreadTest.main(ThreadTest.java:49)
[/code]



code
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadTest {
private static final int MAX_RUNNABLES = 1;

private final List<Runnable> runnableBuffer = new ArrayList<Runnable>(MAX_RUNNABLES);

private final ThreadPoolExecutor myThreadPool =
new ThreadPoolExecutor(MAX_RUNNABLES,
MAX_RUNNABLES,
0L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
public ThreadTest() {
myThreadPool.prestartAllCoreThreads();

for (int i=0; i<MAX_RUNNABLES; i++) {
runnableBuffer.add(new Runnable() {
public void run() {
}
});
}
}

public void start() {

for (Runnable r : runnableBuffer) {
System.out.println("corePoolSize: " + myThreadPool.getCorePoolSize());
System.out.println("maxPoolSize: " + myThreadPool.getMaximumPoolSize());
System.out.println("poolSize: " + myThreadPool.getPoolSize());
System.out.println("taskCount: " + myThreadPool.getTaskCount());

System.out.println("Starting runnable ");
System.out.println("");
myThreadPool.execute(r);
}
System.out.println("All runnables have started");
}

public static void main(String[] args) {
ThreadTest t = new ThreadTest();
t.start();
}
}
[/code]
Updated on 2005-03-31T16:50:08Z at 2005-03-31T16:50:08Z by SystemAdmin
  • SystemAdmin
    SystemAdmin
    1240 Posts

    Re: Problem with Threadpool and Java 1.5

    ‏2005-03-20T19:06:18Z  
    You should not use a synchronous queue with a fixed sized thread pool unless you are sure that there will always be spare threads. SynchronousQueue requires a thread to be waiting for the handoff to succeed; if the thread pool is full, it will trigger the saturation policy. Use a LinkedBlockingQueue; or just use the Executors.newFixedThreadPool() factory.
  • SystemAdmin
    SystemAdmin
    1240 Posts

    Re: Problem with Threadpool and Java 1.5

    ‏2005-03-20T20:32:28Z  
    You should not use a synchronous queue with a fixed sized thread pool unless you are sure that there will always be spare threads. SynchronousQueue requires a thread to be waiting for the handoff to succeed; if the thread pool is full, it will trigger the saturation policy. Use a LinkedBlockingQueue; or just use the Executors.newFixedThreadPool() factory.
    Thanks for the response. But in my model, I have a fixed number of objects that will be place into a thread, so there should never be more requests than there are threads. In the code I posted, I set MAX_RUNNABLES to 1, but whatever it is set to, it is the same number used for the number of tasks to execute (runnableBuffer) as well as the size of the Thread Pool.

    The reason I don't like using the thread pools returned by Executors, is that it returns an ExecutorService instead of returning a ThreadPoolExecutor. The later has some useful methods. Not sure why it was done this way.
  • SystemAdmin
    SystemAdmin
    1240 Posts

    Re: Problem with Threadpool and Java 1.5

    ‏2005-03-28T22:53:05Z  
    Thanks for the response. But in my model, I have a fixed number of objects that will be place into a thread, so there should never be more requests than there are threads. In the code I posted, I set MAX_RUNNABLES to 1, but whatever it is set to, it is the same number used for the number of tasks to execute (runnableBuffer) as well as the size of the Thread Pool.

    The reason I don't like using the thread pools returned by Executors, is that it returns an ExecutorService instead of returning a ThreadPoolExecutor. The later has some useful methods. Not sure why it was done this way.
    This was the subject of a long debate within the Expert Group. In the end, the "undercommit and overdeliver" approach won out.

    In reality, most of the factory methods return ThreadPoolExecutor; you could use an "assert executor instanceof ThreadPoolExecutor" in your code after the construction, and then cast it safely. (The newSingleThreadExecutor is unusual, in that it returns a wrapper class that enforces that it not be upcast, for safety reasons.)

    In any case, SynchronousQueue is a bad match for a fixed-sized thread pool. Did you try it with the Executors factory? Did you try it with a more suitable queue?
  • SystemAdmin
    SystemAdmin
    1240 Posts

    Re: Problem with Threadpool and Java 1.5

    ‏2005-03-29T01:36:32Z  
    I thought that a SynchronousQueue would be ok for a fixed-sized thread pool if the number of tasks was also fixed. It does seem to work better if I used a different Blocking Queue, but it still doesn't make sense to me why my code doesn't work, at least some of the time. It appears to be some timing or synchronization problem.
  • SystemAdmin
    SystemAdmin
    1240 Posts

    Re: Problem with Threadpool and Java 1.5

    ‏2005-03-31T16:50:08Z  
    I thought that a SynchronousQueue would be ok for a fixed-sized thread pool if the number of tasks was also fixed. It does seem to work better if I used a different Blocking Queue, but it still doesn't make sense to me why my code doesn't work, at least some of the time. It appears to be some timing or synchronization problem.
    If the number of tasks is smaller than the number of threads in the pool, then it might be OK. But the interaction between the queue and the thread pool is complicated, and SynchronousQueue is not really a queue. The factory methods in Executors are provided for just this reason -- the relationship between the arguments to new ThreadPoolExecutor is complicated.

    If the reason you chose SQ is that you think it will be faster, I sense premature optimization. Make it right first, then make it fast (if it isn't fast enough, usually it is.)