2

I am creating "big threads", let's name them A, B, C... and put them in a queue. Each of these "big threads" are creating sub threads inside them. a1, a2, a3, b1, b2, b3, c1, c2, c3...

What I do is checking if A is TERMINATED and then starting the B and so on. But when A is finished a1, a2, a3 is starting and running simultaneously, and A becames TERMINATED. So B is starting right after with b1, b2, b3. I don't want this happen. How can I check or make A wait a1, a2, b3 and then be TERMINATED?

I've simplified and anonymized the code but the basic idea is the same:

Here is where runnable foo class is created and added to the queue FYI:

RunnableFooClass rc = new RunnableFooClass();
Thread t = new Thread(rc);

Here is run method of runnable bar class("sub thread") created inside runnable foo class ("big thread")

@Override
public void run() {
    for(int i=0; i<Constants.THREAD_NUM; i++){
         //initialize t
         t.start
    }
}

Following code is in an endless loop:

if(jobQueue.peek().getState() == Thread.State.TERMINATED){
    try {
        jobQueue.peek().join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(jobQueue.poll().getName() + "end.");
}
if(jobQueue.peek() != null){
    jobQueue.peek().start();
    System.out.println(jobQueue.peek().getName() + "start.");
}
nulladex
  • 33
  • 6
  • 1
    https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Phaser.html – Murat Karagöz Aug 04 '16 at 12:03
  • (Aside from your direct question) Running in an endless loop waiting for a thread to be TERMINATED is a terrible idea. join it instead. And why not take it out of the queue *before* running it? Then you don't need to "peek" - just wait for something in the queue. – RealSkeptic Aug 04 '16 at 12:05
  • If `jobQueue.peek().getState() == Thread.State.TERMINATED`, why do you need to `jobQueue.peek().join()`? – Andy Turner Aug 04 '16 at 12:08
  • +1 @MuratK. for Phaser. There are no sub threads in java. All new thread will be created as separate entity. So applying join will be tricky. Phaser can be used instead. https://dzone.com/articles/java-7-understanding-phaser – ankidaemon Aug 04 '16 at 12:08
  • @RealSkeptic that endless loop is checking other things and adds new threads to the queue. How can I deal with it other than this ? – nulladex Aug 04 '16 at 12:12
  • Have one thread that adds to the queue, and another that reads from it and takes care of it, for example. Without knowing the full details it's hard to help. – RealSkeptic Aug 04 '16 at 12:17
  • Thanks @RealSkeptic . – nulladex Aug 04 '16 at 12:30
  • It does not make sense to use three different threads to do three different tasks _in sequence_. If you want to be sure that task B does not start until task A is finished and task C does not start until task B is finished, then the right way to do that is to perform tasks A, B, and C in a single thread. – Solomon Slow Aug 04 '16 at 13:28
  • Another way that sometimes makes sense is to submit tasks A, B, and C to a _single threaded_ executor. (see [`Executors.newSingleThreadExecutor()`](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html#newSingleThreadExecutor%28%29)) – Solomon Slow Aug 04 '16 at 13:31

1 Answers1

2

The basic solution is to use CountDownLatch.

In thread A create a latch initialized THREAD_NUM and pass it to each subthread:

@Override
public void run() {
    CountDownLatch latchA = new CountDownLatch(Constants.THREAD_NUM);
    for(int i=0; i<Constants.THREAD_NUM; i++){
         RunnableFooClass rc = new RunnableFooClass(latchA);
         Thread t = new Thread(rc);
         t.start();
    }
    latchA.await(); // wait for termination of all subthreads
}

Then, at the very end of the subthread's run()

latchA.countDown();
noscreenname
  • 3,314
  • 22
  • 30
  • 1
    +1 for basic solution, however in long run Phaser is more beneficial. http://stackoverflow.com/questions/6830904/java-tutorials-explanations-of-jsr166y-phaser – ankidaemon Aug 04 '16 at 12:19
  • @ankidaemon You're right Phaser is more advanced and allows more flexibility, but is less frequently used (in my experience). Personally, I tend to use simple structures when they are sufficient. Anyhow, thank you for pointing to the other question, it had some interesting answers. – noscreenname Aug 04 '16 at 12:32
  • Agreed with @noscreenname. Yes Phaser is less frequently used as I also didn't came across Phaser at my org – Imran Aug 04 '16 at 12:43
  • @noscreenname Tried, and now it's solved. Thanks. Thank you all. – nulladex Aug 04 '16 at 12:54