Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3460448
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 18, 20262026-05-18T10:13:50+00:00 2026-05-18T10:13:50+00:00

Conventional wisdom tells us that high-volume enterprise java applications should use thread pooling in

  • 0

Conventional wisdom tells us that high-volume enterprise java applications should use thread pooling in preference to spawning new worker threads. The use of java.util.concurrent makes this straightforward.

There do exist situations, however, where thread pooling is not a good fit. The specific example which I am currently wrestling with is the use of InheritableThreadLocal, which allows ThreadLocal variables to be “passed down” to any spawned threads. This mechanism breaks when using thread pools, since the worker threads are generally not spawned from the request thread, but are pre-existing.

Now there are ways around this (the thread locals can be explicitly passed in), but this isn’t always appropriate or practical. The simplest solution is to spawn new worker threads on demand, and let InheritableThreadLocal do its job.

This brings us back to the question – if I have a high volume site, where user request threads are spawning off half a dozen worker threads each (i.e. not using a thread pool), is this going to give the JVM a problem? We’re potentially talking about a couple of hundred new threads being created every second, each one lasting less than a second. Do modern JVMs optimize this well? I remember the days when object pooling was desirable in Java, because object creation was expensive. This has since become unnecessary. I’m wondering if the same applies to thread pooling.

I’d benchmark it, if I knew what to measure, but my fear is that the problems may be more subtle than can be measured with a profiler.

Note: the wisdom of using thread locals is not the issue here, so please don’t suggest that I not use them.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-18T10:13:51+00:00Added an answer on May 18, 2026 at 10:13 am

    Here is an example microbenchmark:

    public class ThreadSpawningPerformanceTest {
    static long test(final int threadCount, final int workAmountPerThread) throws InterruptedException {
        Thread[] tt = new Thread[threadCount];
        final int[] aa = new int[tt.length];
        System.out.print("Creating "+tt.length+" Thread objects... ");
        long t0 = System.nanoTime(), t00 = t0;
        for (int i = 0; i < tt.length; i++) { 
            final int j = i;
            tt[i] = new Thread() {
                public void run() {
                    int k = j;
                    for (int l = 0; l < workAmountPerThread; l++) {
                        k += k*k+l;
                    }
                    aa[j] = k;
                }
            };
        }
        System.out.println(" Done in "+(System.nanoTime()-t0)*1E-6+" ms.");
        System.out.print("Starting "+tt.length+" threads with "+workAmountPerThread+" steps of work per thread... ");
        t0 = System.nanoTime();
        for (int i = 0; i < tt.length; i++) { 
            tt[i].start();
        }
        System.out.println(" Done in "+(System.nanoTime()-t0)*1E-6+" ms.");
        System.out.print("Joining "+tt.length+" threads... ");
        t0 = System.nanoTime();
        for (int i = 0; i < tt.length; i++) { 
            tt[i].join();
        }
        System.out.println(" Done in "+(System.nanoTime()-t0)*1E-6+" ms.");
        long totalTime = System.nanoTime()-t00;
        int checkSum = 0; //display checksum in order to give the JVM no chance to optimize out the contents of the run() method and possibly even thread creation
        for (int a : aa) {
            checkSum += a;
        }
        System.out.println("Checksum: "+checkSum);
        System.out.println("Total time: "+totalTime*1E-6+" ms");
        System.out.println();
        return totalTime;
    }
    
    public static void main(String[] kr) throws InterruptedException {
        int workAmount = 100000000;
        int[] threadCount = new int[]{1, 2, 10, 100, 1000, 10000, 100000};
        int trialCount = 2;
        long[][] time = new long[threadCount.length][trialCount];
        for (int j = 0; j < trialCount; j++) {
            for (int i = 0; i < threadCount.length; i++) {
                time[i][j] = test(threadCount[i], workAmount/threadCount[i]); 
            }
        }
        System.out.print("Number of threads ");
        for (long t : threadCount) {
            System.out.print("\t"+t);
        }
        System.out.println();
        for (int j = 0; j < trialCount; j++) {
            System.out.print((j+1)+". trial time (ms)");
            for (int i = 0; i < threadCount.length; i++) {
                System.out.print("\t"+Math.round(time[i][j]*1E-6));
            }
            System.out.println();
        }
    }
    }
    

    The results on 64-bit Windows 7 with 32-bit Sun’s Java 1.6.0_21 Client VM on Intel Core2 Duo E6400 @2.13 GHz are as follows:

    Number of threads  1    2    10   100  1000 10000 100000
    1. trial time (ms) 346  181  179  191  286  1229  11308
    2. trial time (ms) 346  181  187  189  281  1224  10651
    

    Conclusions: Two threads do the work almost twice as fast as one, as expected since my computer has two cores. My computer can spawn nearly 10000 threads per second, i. e. thread creation overhead is 0.1 milliseconds. Hence, on such a machine, a couple of hundred new threads per second pose a negligible overhead (as can also be seen by comparing the numbers in the columns for 2 and 100 threads).

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Conventional wisdom states that stored procedures are always faster. So, since they're always faster,
Question: Is exception handling in Java actually slow? Conventional wisdom, as well as a
If you use an EnumSet to store conventional binary values (1,2,4 etc), then when
I've only written a small amount of JavaScript that runs embedded in a Java
I have an ASP.NET MVC 2 project that renders conventional strongly typed pages, but
What is Couch DB? How is that different from conventional oracle DB? What is
Conventional IPv4 dotted quad notation separates the address from the port with a colon,
Or would a conventional client-server VCS be more appropriate? I'm currently using TortoiseSVN, but
In the Fibonacci sequence, I have seen conventional implementations which recursively call the same
The SQL-LDR documentation states that you need to do a convetional Path Load: When

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.