-1

Is there a method or utility to determine how many threads can be created in a program, for example with Executors.newFixedThreadPool(numberThreads)? The following custom rollout works but is obviously not an enterprise grade solution:

public class ThreadCounter {
    public static void main(String[] args) {
        System.out.println("max number threads = " + getMaxNumberThreads());
    }

    static int getMaxNumberThreads() {
        final int[] maxNumberThreads = {0};
        try {
            while (true) {
                new Thread(() -> {
                    try {
                        maxNumberThreads[0]++;
                        Thread.sleep(Integer.MAX_VALUE);
                    } catch (InterruptedException e) {
                    }
                }).start();
            }
        } catch (Throwable t) {
        }
        return maxNumberThreads[0];
    }
}
newToScala
  • 397
  • 4
  • 16
  • Creating more threads than the number of logical processors is usually ineffective from a performance point of view. Anyway, any limit is likely to be imposed by the OS, both Windows and Linux have compromises in terms of total virtual memory/stack size of each thread. – Margaret Bloom Oct 08 '16 at 17:30
  • There are plenty of cases to have more threads than the number of cores, for example with blocking IO. – newToScala Oct 08 '16 at 17:32
  • Yes, but *from a performace pov* nothing changes, a blocked thread doesn't affect anything. Unless you want to stress test the system, you should just create the number of threads you want. Anyway, Windows by default has 2048 threads per process, [Linux has editable limits](https://stackoverflow.com/questions/344203/maximum-number-of-threads-per-process-in-linux). – Margaret Bloom Oct 08 '16 at 17:38
  • I'm dealing with a system that is 99.99% IO bound and so even at 2000 threads the CPU usage is less than 10% but at 2100 threads an exception is thrown about too many threads. – newToScala Oct 08 '16 at 17:43
  • 1
    This is clearly an XY-problem, the soon you realise that the sooner you can find the solution you are looking for. You threw 2000 threads at your OS and that did nothing, are you confident that throwing 4000 (or any other upper bound) would change anything? I believe you are stumbling upon a basic misconception: IO-bound processes **don't** need more threads. – Margaret Bloom Oct 08 '16 at 17:53
  • Increasing the number of threads linearly increases throughput. IDK how else could the system be architected besides increasing thread count. – newToScala Oct 08 '16 at 18:01

1 Answers1

1

So as a general rule, creating more threads than the number of processors you have isn't really good because you may find bottlenecks between context switching. You can find the number of threads using the available availableProcessors() method like so:

numThreads = Runtime.getRuntime().availableProcessors();
executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(numThreads);

This provides good general scalability as all available processors will be used in your thread pool.

Now sometimes, due to a lot of I/O blocking, or other factors, you may find that it may make sense to increase the number of threads beyond what you have available. In which case you can just multiply the result of numThreads for example to double the thread pool:

executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(numThreads * 2);

I would only recommend this once some benchmarking has been done to see if it's worth it though.

So it's not a max theoretical limit as such (which will be determined by the underlying operating system), but it probably provides you with the realistic limit of being able to take advantage of your computer's hardware.

Hope this helps!

Dan Conn
  • 59
  • 5
  • Does not answer the question. – newToScala Oct 08 '16 at 21:31
  • Personally, I think it does. Having more threads running than the number of processors is generally bad form. You just create more inefficiency because no matter how many threads you create, you can only ever run x threads concurrently, where x is the number of processors available. To run more means you are are just wasting time context switching. – Dan Conn Oct 08 '16 at 21:35
  • It is not bad form to have more threads than number of processors. If a thread is 100% service time than you are correct. The accepted algorithm for number of threads is numberCores * (1 + waitTime / ServiceTime). For an application that is very IO heavy, the calcuation can be numberCores * (1 + 10000 / 1). You are simply wrong. Refer to the bible (Concurrency in Practice) for explaination. – newToScala Oct 09 '16 at 01:15
  • OK. I'm pretty sure that trying to run 10000 threads when you only have four cores is going to run very slowly in general. I/O blocking or not. Most benchmarks find that with no I/O, 1 thread per processor works best, but even if you had a lot of I/O then normally there's an issue somewhere between 20 and 100 threads where your program does not get any quicker. Relationships between threads, I/O and running time are never a one size fits all thing. Can I just also say, your question has no mention of any I/O use, therefore perhaps you should provide more information so people can factor this – Dan Conn Oct 09 '16 at 08:58
  • 1
    Hi @newToScala - I've just created a FileWalker in Java 8 which goes through 7000 1k files and looks for a search term. I found that just at the number of cores execution time was 6.6s on average Number of cores + 1 = 6.6s on average. Number of cores + 5 = 7.6s on average. Number of cores + 10 = 9.6s on average. Number of cores + 100 = over 30s on average. So it seems that even with I/O blocking in Java 8, matching threads to cores seems to be a generally good option. I might refer you to Goetz's book at 6.1 where he also states that high numbers of threads should be avoided. – Dan Conn Oct 09 '16 at 13:53