-3

I'm in a situation where I have 4 groups of 7 threads each. My CPU (core i7) is supposed to be able to handle 8 threads, so I'm considering going through each group one at a time, running the 7 threads, then moving to the 2nd group, running its 7 threads, then 3rd and 4th groups in the same way, and then starting back at 1st group, until user sends a stop command.

My question is, once each group of 7 threads has finished processing, should I keep those threads idle, or shut them down completely and restart a new group of 7 threads at the next iteration? Which method will be faster? This is for a very speed intensive app, so I need everything to happen as quickly as possible.

I will be using a FixedThreadPool to manage each group of 7 threads. So I could either just invokeAll() and then leave them alone (presumably to idle), or I could shutdown() each threadpool after the invokeAll() and start a new thread pool at the next iteration.

Which method will be faster?

Roman C
  • 49,761
  • 33
  • 66
  • 176
Ali
  • 261,656
  • 265
  • 575
  • 769

4 Answers4

4

My question is, once each group of 7 threads has finished one cycle of processing, should I keep those threads idle, or shut them down completely and restart a new group of 7 threads at the next cycle?

I would use a single ExecutorService thread-pool and reuse the same threads for all tasks. See the tutorial on the subject. A thread-pool is designed to execute any Runnable or Callable class so they are task agnostic. For example, you might have ParentResult and ChildResult classes. You can submit a Callable<ParentResult> to the thread-pool which will return a Future<ParentResult> and you can submit a Callable<ChildResult> to the same thread-pool which will return a Future<ChildResult>.

The only reason why you'd want to have "groups of threads" is if each thread has some state that it must maintain -- a database connection or something. Even then many people use thread-pools since it does much of the concurrency heavy lifting for you.

If you do have to keep this state then I would certainly not shutdown the pools and then restart them later. A dormant thread/pool is taking no system resources aside from memory. The only reason why you would ever do this is if you are forking 100s of thread for the task but at that point, you should consider re-architecting your application.

Gray
  • 115,027
  • 24
  • 293
  • 354
  • Thanks. I need to have 4 groups of threads, because each group will be processing a specific item. So the top 4 groups will return `Future`, and the bottom 24 threads will return `Future`, the `ChildResult`s will all be gathered together by the `ParentResult` before it will deliver a final `Result`.. – Ali Oct 07 '13 at 15:11
  • The thread-pool has nothing to do with the `Future` that is returned @ClickUpvote. You can (and should) submit a `Callable` and a `Callable` to the _same_ thread-pool. – Gray Oct 07 '13 at 15:13
  • While we're on the topic, could you tell me, what happens if a `shutDownNow()` is called on the threadpool while it still has some `Callable` items which are being processed right now? I don't have a `run()` method in the callables, so I don't know if they will be immediately interrupted or allowed to finish – Ali Oct 07 '13 at 15:16
  • `shutdownNow()` dequeues the tasks that have yet to be run and interrupts the threads that are running. That doesn't mean that those threads will stop unless they are looking for the interrupt. See here @ClickUpvote: http://stackoverflow.com/questions/9791361/thread-not-interrupting/9791479#9791479 – Gray Oct 07 '13 at 15:18
  • What's the default behavior, do they look for the interrupt by default or not? As I said I don't a `run()` method in my Callables, only `call()`, so I assume the `run()` will be added by the JDK and it will manage them in some default way.. – Ali Oct 07 '13 at 15:20
  • Huh? This has got nothing to do with `run()` nor with `call()`. Please read the link I posted. Any thread can get interrupted. All it is setting a bit on the thread. _If_ you then call `Thread.sleep()` and other methods they will throw `InterruptedException`. Otherwise you have to test for the interrupt flag. Read that link please @ClickUpvote. – Gray Oct 07 '13 at 15:24
  • I've read it, and I understand that in your thread's run() method, you need to check for InterruptedException in order to shut it down when interrupted. But since I'm just using callable objects with no `run` methods, I don't know what the JVM's default implementation of run is, and whether or not these threads will be shut down when interrupted. – Ali Oct 07 '13 at 15:52
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/38731/discussion-between-gray-and-click-upvote) – Gray Oct 07 '13 at 15:54
1

When you say your processor has 8 threads, I think you mean it has has 4 cores with hyperthreading. Java does not use threads in the same sense as your processor, so those 7 threads are of a different type to your processors.

The JVM handles processor usage, and is (IIRC) limited to using 1 core. The threads java uses are specific to the JVM, and are wholly separate.

As for your actual question, try testing different thread combinations to see which is fastest, which will give you a more accurate answer than arm-chair theorising.

1

You need not to schedule your threads manually. Start all 28 threads at once - this would not be slower, but well can be faster.

Alexei Kaigorodov
  • 13,189
  • 1
  • 21
  • 38
0

I too prefer Alexei Kaigorodov suggestion to start all 28 threads. But I suggest you to replace newFixedThreadPoolwith new Executors API: ( since Java 8)

static ExecutorService  newWorkStealingPool()

Creates a work-stealing thread pool using all available processors as its target parallelism level.

Above API returns ForkJoinPool type of ExecutorService

Now you don't need to worry utilization of idle threads. Java will take care better utilization of idle threads with work-stealing mechanism.

If you still need four different groups of FixedThreadPools, you can proceed with invokeAll. Don't shutdown ExecutorService to switch between multiple pools. You one ExecutorService effectively. If you want to poll the result of Future tasks using invokeAll, use CompletableFuture and poll it to know the status of task execution.

static CompletableFuture<Void>  runAsync(Runnable runnable, Executor executor)

Returns a new CompletableFuture that is asynchronously completed by a task running in the given executor after it runs the given action.

Ravindra babu
  • 37,698
  • 11
  • 250
  • 211