0

I have a thread pool executor

private ExecutorService exec=Executors.newCachedThreadPool();

and I have a class

class MyCallable implements Callable<String>{

    private ReentrantLock lock=new ReentrantLock();

    private Condition cond=lock.newCondition();


    public String call(){

    System.out.println("TEST!!);
    try{
      lock.lock();
      cond.await();
    }finally{
       lock.unlock();
    }
   }
}

and I do:

for(int i=0;i<10000;i++){
   exec.submit(new MyCallable());
}

I want to have 10000 threads with waiting callables, but I can see only one TEST!! in my logs, so it submits my task only once, why it freezes??? My callable has it`s own lock in each object instance, how to have 1000 waiting threads?

JimmyB
  • 12,101
  • 2
  • 28
  • 44
avalon
  • 2,231
  • 3
  • 24
  • 49
  • How long do you keep waiting after the `for(...)` loop is through before terminating the program? – JimmyB May 27 '15 at 12:27
  • **[Executors#newFixedThreadPool will probably help you in what you want to achieve](http://stackoverflow.com/a/949463/3143670)** – Neeraj Jain May 27 '15 at 12:28
  • Thank you,but Ican`t use fixed thread pool, I don't know number of callables, 10k just an example @Hanno, I have only this loop, I even don't use future.get() – avalon May 27 '15 at 12:32
  • Could it be that your program terminates before many of the new threads get even executed? What happens if you just `Thread.sleep(1000)` after the loop? – JimmyB May 27 '15 at 12:34
  • You dont need to know the number of callables anyway. FixedThreadPool is just executing n threads at a time. – Stefan May 27 '15 at 12:35
  • Thank you, but fixed thread pools hasn't done the trick either. – avalon May 27 '15 at 12:49

3 Answers3

1

I took your code, filled in the missing bits, fixed the compilation errors and ran it. It prints "TEST!!" lots of times. If I reduce the number of tasks to a reasonable number, it runs to completion. If I leave it at 10,000 the test fails with an OOME saying that it can't allocate any more thread stacks.


I want to have 10000 threads with waiting callables

My testing suggests that that many threads is going to cause you to run out of memory. It is really, really not a good idea.


Here is the exact code I used:

package test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorTest {

    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < 10000; i++) {
            exec.submit(new MyCallable());
        }
    }
}


package test;

import java.util.concurrent.Callable;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

class MyCallable implements Callable<String> {

    private ReentrantLock lock = new ReentrantLock();

    private Condition cond = lock.newCondition();

    public String call() {

        System.out.println("TEST!!");
        try {
            lock.lock();
            cond.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return "foo";
    }
}

Here's the while(true) {await} test:

[steve@newbox ~]$ cat ./workspace/test/src/test/CondAwait.java 
package test;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class CondAwait {

    public static void main(String[] args) throws InterruptedException {
         ReentrantLock lock = new ReentrantLock();

         Condition cond = lock.newCondition();
         lock.lock();
         while(true){
             System.out.println("Hi!");
             cond.await();
         }
    }

}
[steve@newbox ~]$ java -cp ./workspace/test/bin test.CondAwait 
Hi!
^C[steve@newbox ~]$ 

In short, the main thread freezes in the first await call ... as I would have expected.


I agree that it`s not a good idea, but those threads will be like a request cache, user sends a request, it's processor should be put into the thread pool, if we have 10k requests per second, you will see 10k threads in the pool. Please suggest how to do it better.

Use a bounded thread pool, and set the bound to be roughly equal to the number of cores that you have.

Sure, you won't have your 10,000 callables all suspended at the same time, but that is a GOOD THING.

If these callables are meant to simulate requests that wait a few seconds for a something external to respond, then a thread pool of up to 100 might be reasonable. But if you really, really need massive parallelism then you should be looking at something that uses NIO selectors so that a small number of worker threads can run a large number of requests, interleaving them rather than blocking in I/O.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Thank you, that's really odd, please try to run while(true){cond.await();} Thank you – avalon May 27 '15 at 12:39
  • Thank you, I agree that it`s not a good idea, but those threads will be like a request cache, user sends a request, it's processor should be put into the thread pool, if we have 10k requests per second, you will see 10k threads in the pool. Please suggest how to do it better. Thank you – avalon May 27 '15 at 12:43
  • Thank you, but why I need to hold a lock if I called lock.lock() before, and it's not explaining why I can't see statements before await. – avalon May 27 '15 at 13:02
  • And I also noticed that my unprocessed messages begins to process before tomcat shutdown. Weird :/ – avalon May 27 '15 at 13:11
  • Thank you, yes it's may be a good idea but why I can't have 100 threads running simultaneously and suddenly an external service felt down, and they 100 will just stuck in the air. is it bad? Of course we will have future.get(10,TimeUnit.SECONDS), but I even can`t start more than one thread that runs in indefinite loop. – avalon May 27 '15 at 13:50
  • I found it. It works only with new SynchronousQueue() - no other queues are accepted, so when first job running infinite loop, queue gets blocked I guess – avalon May 27 '15 at 14:11
0

Have a look at the class java.util.concurrent.CyclicBarrier. As stated in its JavaDoc it is:

A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.

Each of your threads needs to call the method await of the barrier. This means that the thread is suspended until either the Barrier has reached the expected number of threads or a timeout has occured.

Steven Pessall
  • 983
  • 5
  • 15
0

I just tried you program and it works fine for me. I could see multiple tasks running.

public class MyCallable implements Callable<String> {

    private ReentrantLock lock = new ReentrantLock();
    private Condition cond = lock.newCondition();

    public String call() {
        System.out.println("TEST!!");
        try {
           lock.lock();
           cond.await();
        } catch (InterruptedException e) {
           e.printStackTrace();
        } finally {
           lock.unlock();
        }
        return "done";
    }

    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
           service.submit(new MyCallable());
        }
    }
}

And I would suggest 10000 concurrent tasks is not a good idea. How many processors you have? ;)

hemant1900
  • 1,226
  • 8
  • 9
  • Thank you, it doesn't matter for me, as I need to store somewhere threads that will wait for rabbitmq response, how can I do that? I have no idea. – avalon May 27 '15 at 12:58