Execute two threads which wait one for the other while main thread continues

26,237

Solution 1

The second Thread can be custom like this (takes as argument the previous thread):

public static void main(String[] a) {
    Thread first = new Thread(new Runnable() {
        @Override
        public void run() {

        }
    });

    Thread second = new MyThread(first);
    first.start();
    second.start();

    //continue executing
}

public static class MyThread extends Thread {

    private Thread predecessor;

    public MyThread(Thread predecessor) {
        this.predecessor = predecessor;
    }

    public void run() {
        if (predecessor != null && predecessor.isAlive()) {
            try {
                predecessor.join();
            } catch (InterruptedException e) {}
        }
        //do your stuff
    }
}

Solution 2

I am pretty sure you got something wrong because this must work and it does work:

new Thread() {
    @Override
    public void run() {
        TestThread t1= new TestThread("1");
        TestThread t2= new TestThread("2");
        try {
            t1.start();
            t1.join();
            t2.start();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}.start();

The ouput is:

main is Started
Hello
Thread 1 is Started
Thread 1 is Completed
Thread 2 is Started
Thread 2 is Completed

Another option would be to extend the TestThread for the "Thread 1" to execute the work of "Thread 2" after it has been done with its own work. Something similar to this:

final TestThread t2= new TestThread("2");
TestThread t1= new TestThread("1") {
    @Override
    public void run() {
        super.run(); //finish t1 work
        t2.start();  // start t2 work
    }
};
t1.start();

Solution 3

You can use a CountDownLatch:

create it in the main thread, pass it on to both threads and call countdown on it in thread one when it exits and await it being counted down at the start of thread 2.

Solution 4

Try this, This will work as expected. Two threads printing odd and even one after another and main exiting as soon as possible.

public class YoThreD {

    static boolean isThread1 = false;

    public static synchronized boolean isThread1() {
        return isThread1 = !isThread1;
    }

    public static void main(String args[]) {

        Runnable runnableObject = new Runnable() {
            @Override
            public void run() {
                synchronized (this) {
                    for (int i = 1; i <= 100; i++) {
                        try {
                            if (Thread.currentThread().getName().equals("thread1")) {
                                if (isThread1()){
                                    System.out.println(Thread.currentThread().getName() + "    :   " + i);
                                }else{
                                    this.notify();
                                    this.wait();
                                }
                            } else {
                                if (!isThread1()){
                                    System.out.println(Thread.currentThread().getName() + "    :   " + i);
                                    this.notify();
                                    this.wait();
                                }
                                else{
                                }
                            }
                        } catch (Exception e) {
                        }
                    }
                }
            }
        };
        Thread thread1 = new Thread(runnableObject);
        thread1.setName("thread1");
        thread1.start();
        Thread thread2 = new Thread(runnableObject);
        thread2.setName("thread2");
        thread2.start();
        System.out.println(Thread.currentThread().getName() + "Main thread finished");
    }
}

Solution 5

Why not just have thread1 be the one to start thread2?

// in main
new Thread(new Runnable() {
    @Override public void run() {
        // do thread1 work
        new Thread(new Runnable() {
              @Override public void run() { /* do thread2 work */ }
        }).start();
    }
}).start();

However, it's not at all clear why you would want to do this as opposed to just having thread1 do 100% of the background work.

Share:
26,237
dendini
Author by

dendini

Updated on July 10, 2020

Comments

  • dendini
    dendini almost 4 years

    How can I start two threads where thread1 executes first, thread2 starts when thread1 ends while the main method thread can continue its work without locking on the other two?

    I have tried join() however it needs to be called from the thread which has to wait for the other, there's no way to do something like thread2.join(thread1); If I call for a join inside main() I therefore effectively stop execution of the main thread and not only of thread2.

    I therefore tried with ExecutorService but again same problem.

    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    
    public class Test
    {
        public static void main(String args[]) throws InterruptedException
        {
            System.out.println(Thread.currentThread().getName() + " is Started");
    
            class TestThread extends Thread
            {
                String name;
                public TestThread(String name)
                {
                    this.name = name;
                }
    
                @Override
                public void run()
                {
                    try
                    {
                        System.out.println(this + " is Started");
                        Thread.sleep(2000);
                        System.out.println(this + " is Completed");
                    }
                    catch (InterruptedException ex)  {  ex.printStackTrace(); }
                }
    
                @Override
                public String toString()  { return "Thread " + name; }
            }
    
            ExecutorService executor = Executors.newCachedThreadPool();
            executor.execute(new TestThread("1"));
    
            boolean finished = executor.awaitTermination(1, TimeUnit.HOURS);
    
            if(finished)
            {
               //I should execute thread 2 only after thread 1 has finished
                executor.execute(new TestThread("2"));
            }
    
            //I should arrive here while process 1 and 2 go on with their execution
            System.out.println("Hello");
        }
    }
    

    #EDIT: Why I need this:

    I need this because Thread1 copies elements from a database table into another database, thread2 has to copy a linking table which references the table copied from thread1. Consequently thread2 has to start populating its linking table only when thread1 has finished otherwise an integrity error is given by the database. Now imagine I have several threads with different priorities due to complex linking tables and you have an idea.