1

I have a very simple program which uses ExecutorService.

I have set the no. of threads to 4, but the time taken is same as that set to 2.

Below is my code:

public class Test {
     private static final Logger LOGGER = Logger.getLogger("./sample1.log");

    @SuppressWarnings("unchecked")
    public static void main(String[] args) throws Throwable {
        ExecutorService service = Executors.newFixedThreadPool(4);
        Future<String> resultFirst = service.submit(new FirstRequest());
        Future<String> resultSecond = service.submit(new SecondRequest());
        Future<String> resultThird = service.submit(new ThirdRequest());
        Future<String> resultFourth = service.submit(new FourthRequest());

        String temp1 = resultSecond.get();
        temp1 = temp1.replace("Users", "UsersAppend1");

        String temp2 = resultThird.get();
        temp2 = temp2.replace("Users", "UsersAppend2");

        String temp3 = resultFourth.get();
        temp3 = temp3.replace("Users", "UsersAppend3");

        //System.out.println(resultFirst.get() + temp1 + temp2 + temp3);
        //LOGGER.info("Logger Name: "+LOGGER.getName());

        LOGGER.info(resultFirst.get() + temp1 + temp2 + temp3);

        service.shutdownNow();
        service.awaitTermination(10, TimeUnit.SECONDS);

        System.exit(0);
        }
}

Here FirstRequest, SecondRequest, ThirdRequest and FourthRequest are different classes which calls another class which is common to all.

I have created distinct objects for the common class so I don't think it's a case of deadlock/Starvation.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • If you have a shared resource, why do you think it cannot be a "problem" of locking? Is the "common" class thread-safe? – Fildor Mar 07 '17 at 07:03
  • What is the question? – matt Mar 07 '17 at 07:04
  • @matt Question is: why does adding two threads to the pool not speeding up overall execution time. OP: "I have set the no. of threads to 4, *but the time taken is same as that set to 2*." – Fildor Mar 07 '17 at 07:05
  • 1
    You shouldn't be using [`shutdownNow`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#shutdownNow--) but [`shutdown`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#shutdown--), btw. `shutdownNow` won't schedule unstarted tasks. Docs: "Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution." - Shouldn't be a problem here since you wait for the results, but generally speaking. – Fildor Mar 07 '17 at 07:08
  • 1
    We have no idea of what your tasks are doing, and of how you measure the time it takes to execute them. If they're competing for the same shared resource, then you can't expect a speedup. If they're CPU-bound, and you have only 2 cores, you can't expect a speedup. If they're so fast that making them multi-threaded only adds overhead, you can't expect a speedup. – JB Nizet Mar 07 '17 at 07:24
  • @fildor They don't ask that question explicitly and it is completely unrelated to the title. – matt Mar 07 '17 at 08:39
  • Is the real question "why isn't my program running faster with more threads"? – Gray Mar 10 '17 at 05:28
  • @Fildor: I am creating a new object for every new thread that is why I feel though there is a common class it may not be the scenario of locking the resource. – Dinah Chemmannur Jony Mar 13 '17 at 08:59
  • @matt : I just wanted to make the title very brief. Apologies if it has mislead – Dinah Chemmannur Jony Mar 13 '17 at 09:04
  • @Gray: That indeed is my question – Dinah Chemmannur Jony Mar 13 '17 at 09:06
  • @JBNizet : I agree with your comments and answers that using threads depends on the core size and i have 2 cores with 4 logical processors. – Dinah Chemmannur Jony Mar 13 '17 at 09:12
  • You can only have two threads running that are cpu limited. Some tasks will not be cpu limited, and having the additional 'logical processors' can speed up those tasks. Naively, if you have a 2 core 3ghz processor, then you can do 3ghz of processing on two threads, or you could do 1.5 ghz of processing on 4 threads. – matt Mar 13 '17 at 09:31
  • @matt "They don't ask that question explicitly" - Yes, that's why I wrote a *comment*. Just a general hint for OP. – Fildor Mar 13 '17 at 09:36
  • " I am creating a new object for every new thread" - Yes you do. That does not mean they necessarily do not share a common resource that could be a bottleneck or even end up in the threads executing sequentially. Depends on how it is coded, what they are doing. – Fildor Mar 13 '17 at 09:38

3 Answers3

2

You want to start here - meaning: it is actually hard to measure Java execution times in a reasonable way. Chances are that you have an over-simplified view; and thus your measurements aren't telling anything.

And beyond that: you have to understand that "more threads" do not magically reduce overall runtime. It very much depends on what you are doing; and how often for example your threads spend time waiting for IO.

Meaning: "adding" threads only helps when each thread is inactive for "longer" periods of time. When each thread is constantly burning CPU cycles at 100% ... then more threads do not help; to the contrary: then times get worse, because the only thing you do is add overhead for setting up and switching between your tasks.

Community
  • 1
  • 1
GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • Thanks for the explanation but with 2 cores and 4 logical processors can you please tell what could be happening behind the scenes? I have run the program in debug mode and i can see that it gets executed as 2 threads simultaneously though i have given 4. the CPU spends time with 2 threads at a time. – Dinah Chemmannur Jony Mar 13 '17 at 09:13
  • Thanks for the accept. I am half out for vacation (so no keyboard). I will come back to you at some point, but it might take a week... Feel free to drop me a reminder if you don't hear from me by next Monday! – GhostCat Mar 13 '17 at 09:43
0

How many processors do you have ? Time taken depends upon type of task you are performing, type of resources you are using in your tasks etc. Adding more threads doesn't mean your process will become fast, it just mean that if there are idle processing power available, then java will try to use them.

Aman Goyal
  • 383
  • 2
  • 9
0

I have set the no. of threads to 4, but the time taken is same as that set to 2.

This is a very common issue. I've heard of countless times that sometimes works really hard to turn a single-threaded application into a multi-threaded application so find that it doesn't run faster. It actually can run slower because of thread overhead and refactoring issues.

The analogy is a overworked researcher on a project. You could divide their work and give it to 4 graduate students to work concurrently but if they all have to ask the researcher questions all of the time then the project isn't going to go any faster and the lack of coordination between the 4 graduate students can make the project take even longer.

The only times adding additional threads to an application will definitively improve the throughput is when the threads are:

  1. completely independent – i.e. not sharing data (or not a lot) between threads which is when they block or have to synchronize memory
  2. completely CPU bound – i.e. doing only data processing and not waiting on disk or network IO or other system resources
  3. able to make use of additional system CPUs

Here FirstRequest, SecondRequest, ThirdRequest and FourthRequest are different classes which calls another class which is common to all.

Right, this is a red flag. The First/Second/... Request classes may be able to work concurrently but if they have to call synchronized blocks in the common class then they will block each other. One of the tricky things with threaded programming is how to limit the data sharing while still accomplishing their tasks. If you show more of the common class then we might be able to help you more.

The other big red flag is any amount of IO. Watch out for reading and writing to disk or network. Watch also for logging or other output. It is often efficient to have one thread reading from disk, a number of threads processing what is read, and one thread writing. But even then, if the processing isn't very CPU intensive, you might see little to no speed improvement because the speed of the application is limited by the IO bandwidth of the disk device.

Web applications that spawn a thread for every request to be handled can be efficient because they are handling so many network IO bound requests simultaneously. But the real win is the code improvements that come from the thread being able to concentrate on its request and the thread subsystems will then take care of the context switching between requests when the thread is blocked waiting on network or disk IO.

Gray
  • 115,027
  • 24
  • 293
  • 354
  • thanks for the explanation, but just to give you an overview the common class that is been spoken about has an api call, for which i have set different offset and limit values as query param. – Dinah Chemmannur Jony Mar 13 '17 at 17:49
  • To give you an overview, the common class that is been spoken about has an api call. For instance I have an api call http://example.com?offset=1&limit=100 and if i call this api with 'GET' method; without using threads it would provide me the output after 48seconds, and I could not afford that. so when I used threads i.e 2 threads it drastically reduced the time to 25s. all that i did was created 2 more classes, firstRequest and SecondRequest which had individual distinct object of the common class with offset=1 and limit=50 and 2nd offset=51 and limit=100. – Dinah Chemmannur Jony Mar 13 '17 at 17:59
  • So when further increased the number of threads to 4 expecting a better through put. And I was pretty sure that 4 is not a big number. But I guess it's more about the core size. On the contrary I have seen example where they set 5 to 10 threads and they are put in a for loop, and they get easily executed. I am sure missing something in between. – Dinah Chemmannur Jony Mar 13 '17 at 18:01
  • And what is this API doing @DinahChemmannurJony? Is it just CPU processing? – Gray Mar 13 '17 at 18:53
  • Is the API looking up stuff on disk or over the net? Also, any idea of the locking that happens in this API @DinahChemmannurJony ? – Gray Mar 13 '17 at 19:01
  • This Api will give me a list of users in that portal. So if I set the limit and offset to say 100 and 1 respectively then I am gonna get all the users which will take abt 48s, but if I break the values and assign it to separate threads then it made it half with 2 threads, but no luck with 4 threads. That's why I strongly feel it's the core size that matters, i.e I have 2 cores and 4 logical processors. If i can get this deployed on another VM with more cores it might just help me out. So I wanted to know the root cause. – Dinah Chemmannur Jony Mar 14 '17 at 05:42
  • If you see that you are using all available CPU resources then running on a larger instance should give you more throughput @DinahChemmannurJony. – Gray Mar 14 '17 at 20:00