1

I have the following method which is run by some 100+ threads.

<Method Signature>
{
   System.out.println("Starting Thread with ID :- " + iThreadID);

   <Some piece of code which takes more than 10 seconds to complete>

   System.out.println("Finished Thread with ID :- " + iThreadID);
}

When the threads execute, I get the following output.

Starting Thread with ID :- 1
Starting Thread with ID :- 6
Starting Thread with ID :- 14
Starting Thread with ID :- 9
Starting Thread with ID :- 69
Starting Thread with ID :- 21
Starting Thread with ID :- 87
Starting Thread with ID :- 13
Starting Thread with ID :- 10
Starting Thread with ID :- 45
**Finished Thread with ID :- 1**
Starting Thread with ID :- 30
Starting Thread with ID :- 25
Starting Thread with ID :- 32
**Finished Thread with ID :- 87**
...

Not all 100 threads are launched together. Some thread gets to complete its method execution before others are created.

Why is it so? Is there anything I can do to ensure that all the threads are created before the long, time taking piece of code is executed?

Pankaj Dwivedi
  • 379
  • 1
  • 6
  • 16
  • 1
    It would be a lot more annoying if threads would wait around even though you called `start()`. – Kayaman Nov 24 '17 at 06:28
  • How do you start you threads? – Flown Nov 24 '17 at 06:30
  • 1
    @SMA of course you can. Don't be ridiculous. Even though technically only N threads (where N = number of cores) can **literally** be executing ops at the same time, having a hundred runnable threads would still be executing "at the same time" as far as the average human perception goes. – Kayaman Nov 24 '17 at 06:31
  • @SMA you can easily run thousands of threads at the same time on a modern regular desktop computer. You need to read up on some things before you give out misleading information. – Kayaman Nov 24 '17 at 06:35
  • There isn't enough information to answer the question. How would you know when all the threads are started? are they started by a 101st thread? would you do a notifyAll() when they're all created? – Maurice Perry Nov 24 '17 at 06:41
  • @Flown The threads are started using ExecutorService.execute(). – Pankaj Dwivedi Nov 24 '17 at 06:41
  • As for @OP, the easiest way would be to create 100 `Callables` and call `invokeAll()` on an `ExecutorService`. Another way would be to use a `CountDownLatch` to make threads wait until they're all started. – Kayaman Nov 24 '17 at 06:43
  • @Maurice Perry All I want is that all threads must execute a certain set of code before any one of them executes the code after that set. – Pankaj Dwivedi Nov 24 '17 at 06:43
  • 2
    A `CountDownLatch` would work for that. – Kayaman Nov 24 '17 at 06:44
  • @Kayaman Please share an example of "CountDownLatch". I am quite new to creating and managing threads using the feature of the ExecutorService. – Pankaj Dwivedi Nov 24 '17 at 06:45
  • @PankajDwivedi again, how would you know when all the threads are ready to continue? when there are 100 threads waiting? – Maurice Perry Nov 24 '17 at 06:50
  • 2
    You could use a [`CountDownLatch`](https://docs.oracle.com/javase/9/docs/api/java/util/concurrent/CountDownLatch.html) but personally I would prefer a [`CyclicBarrier`](https://docs.oracle.com/javase/9/docs/api/java/util/concurrent/CyclicBarrier.html) – David Conrad Nov 24 '17 at 06:53
  • The magic number 100? – Maurice Perry Nov 24 '17 at 07:00
  • @MauricePerry If all the threads do a certain operation before any of them proceeds to do something after that will tell me that all threads have come into existence. – Pankaj Dwivedi Nov 24 '17 at 07:00
  • Even if you use a CountDownLatch, it doesnt guarantee that all your thread will execute in a order or that it will end together. That is the whole purpose of threads. Run multiple code parallelly that may not cause any difference by the order they execute or is completed. In case you need a specific case where you need to hold for a event, then you may use some kind of Semaphore. – Tharun Nov 24 '17 at 07:01
  • @PankajDwivedi does "all the threads" means "100 threads"? all the threads in the ExecutorService? all the threads that I have started? – Maurice Perry Nov 24 '17 at 07:02
  • @MauricePerry Yes, all 100 threads should first execute statement 1 before any of them executes statement 2. – Pankaj Dwivedi Nov 24 '17 at 07:10
  • 2
    @PankajDwivedi Why do you think that all threads are launched together? This depends on the used `ExecutorService`-implementation. For example the [`ThreadPoolExecutor`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ThreadPoolExecutor.html) will only run a certain number of threads at the same time depending on `maximumPoolSize`. So please add your code where you create the `ExecutorService` and how you use it. –  Nov 24 '17 at 07:10
  • Have you done any prior research? – GhostCat Nov 24 '17 at 07:57
  • I can't decide if i should downvote because [No MCVE](http://idownvotedbecau.se/nomcve) or [Being unresponsive](http://idownvotedbecau.se/beingunresponsive). –  Nov 24 '17 at 08:12
  • @devpuh No offence meant. Here is how I am creating the Executor. ExecutorService executor = Executors.newFixedThreadPool(100). I am a newbie to the thread creation using ExecutorService hence this may not be optimal. But, as several others have suggested, CountDownLatch looks to be doing what I need. – Pankaj Dwivedi Nov 24 '17 at 08:25
  • @PankajDwivedi Please edit your question, so that all necessary information are in the question. By the way when you have a `Executors.newFixedThreadPool(100)` and you want to create over 100 Threads they will never get executed at the same time. –  Nov 24 '17 at 08:34
  • @devpuh Ok! What am I supposed to do to create all the threads at once? – Pankaj Dwivedi Nov 24 '17 at 08:35
  • @PankajDwivedi Please complete/edit your original question. Read carefully [How to create a Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve) and the perviously posted links. It's still unclear what exactly you are asking. –  Nov 24 '17 at 09:17

1 Answers1

8

From comment:

All I want is that all threads must execute a certain set of code before any one of them executes the code after that set.

Use a CountDownLatch. The javadoc describes exactly what you're needing:

A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.

If you want to do it multiple times, use a CyclicBarrier:

A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other. The barrier is called cyclic because it can be re-used after the waiting threads are released.


Here is code showing both.

Test Helper Method

private static void test(int count, Supplier<Thread> threadProducer) {
    Thread[] threads = new Thread[count];
    for (int i = 0; i < count; i++) {
        threads[i] = threadProducer.get();
        threads[i].start();
    }
    System.out.println("Ready");
    for (int i = 0; i < count; i++)
        try {
            threads[i].join();
        } catch (InterruptedException e) {
            System.out.println(threads[i].getName() + ": " + e);
        }
    System.out.println("All Done");
}

CountDownLatch

class LatchThread extends Thread {
    private final CountDownLatch countDownLatch;
    public LatchThread(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }
    @Override
    public void run() {
        try {
            System.out.println(getName() + ": Started");
            this.countDownLatch.countDown();
            this.countDownLatch.await();
            System.out.println(getName() + ": Done");
        } catch (InterruptedException e) {
            System.out.println(getName() + ": " + e);
        }
    }
}

Output shows that threads wait until all have started, i.e. until all have called countDown().

CountDownLatch countDownLatch = new CountDownLatch(10);
test(10, () -> new LatchThread(countDownLatch));
Thread-0: Started
Thread-4: Started
Thread-5: Started
Thread-3: Started
Thread-2: Started
Thread-1: Started
Thread-8: Started
Thread-9: Started
Thread-6: Started
Thread-7: Started
Ready
Thread-7: Done
Thread-4: Done
Thread-2: Done
Thread-0: Done
Thread-6: Done
Thread-8: Done
Thread-1: Done
Thread-9: Done
Thread-3: Done
Thread-5: Done
All Done

CyclicBarrier

class BarrierThread extends Thread {
    private final CyclicBarrier cyclicBarrier;
    public BarrierThread(CyclicBarrier cyclicBarrier) {
        this.cyclicBarrier = cyclicBarrier;
    }
    @Override
    public void run() {
        try {
            System.out.println(getName() + ": Started");
            if (this.cyclicBarrier != null) this.cyclicBarrier.await();
            System.out.println(getName() + ": Phase 1");
            if (this.cyclicBarrier != null) this.cyclicBarrier.await();
            System.out.println(getName() + ": Phase 2");
            if (this.cyclicBarrier != null) this.cyclicBarrier.await();
            System.out.println(getName() + ": Done");
        } catch (InterruptedException | BrokenBarrierException e) {
            System.out.println(getName() + ": " + e);
        }
    }
}

Output shows that threads wait for each other before entering next phase.

CyclicBarrier cyclicBarrier = new CyclicBarrier(10);
test(10, () -> new BarrierThread(cyclicBarrier));
Thread-0: Started
Thread-5: Started
Thread-4: Started
Thread-2: Started
Thread-6: Started
Thread-1: Started
Thread-3: Started
Thread-7: Started
Thread-9: Started
Thread-8: Started
Ready
Thread-8: Phase 1
Thread-5: Phase 1
Thread-4: Phase 1
Thread-6: Phase 1
Thread-0: Phase 1
Thread-9: Phase 1
Thread-7: Phase 1
Thread-3: Phase 1
Thread-1: Phase 1
Thread-2: Phase 1
Thread-2: Phase 2
Thread-8: Phase 2
Thread-6: Phase 2
Thread-7: Phase 2
Thread-1: Phase 2
Thread-4: Phase 2
Thread-5: Phase 2
Thread-3: Phase 2
Thread-9: Phase 2
Thread-0: Phase 2
Thread-0: Done
Thread-8: Done
Thread-4: Done
Thread-2: Done
Thread-9: Done
Thread-3: Done
Thread-5: Done
Thread-1: Done
Thread-6: Done
Thread-7: Done
All Done

By comparison, without a barrier, output shows that threads don't wait for each other.

test(10, () -> new BarrierThread(null));
Thread-0: Started
Ready
Thread-4: Started
Thread-4: Phase 1
Thread-4: Phase 2
Thread-4: Done
Thread-1: Started
Thread-1: Phase 1
Thread-1: Phase 2
Thread-1: Done
Thread-5: Started
Thread-5: Phase 1
Thread-5: Phase 2
Thread-5: Done
Thread-2: Started
Thread-2: Phase 1
Thread-2: Phase 2
Thread-2: Done
Thread-3: Started
Thread-6: Started
Thread-6: Phase 1
Thread-7: Started
Thread-9: Started
Thread-9: Phase 1
Thread-8: Started
Thread-8: Phase 1
Thread-8: Phase 2
Thread-8: Done
Thread-0: Phase 1
Thread-0: Phase 2
Thread-0: Done
Thread-9: Phase 2
Thread-9: Done
Thread-7: Phase 1
Thread-7: Phase 2
Thread-7: Done
Thread-6: Phase 2
Thread-3: Phase 1
Thread-3: Phase 2
Thread-3: Done
Thread-6: Done
All Done
Andreas
  • 154,647
  • 11
  • 152
  • 247
  • Both these classes are fairly new to me. Let me explore further. If you can share a simple, working example of both of them, it will be of big help. – Pankaj Dwivedi Nov 24 '17 at 07:02