Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using join() vs. wait() thread java [closed]

I need to make sequence of threads. They need to start in order like this:

A then B then C and finally D.

When D is finished then C can finish then B, then A.

In this situation what is better to use join() threads or wait()? and why?

My threads need to start and print the message Hello I'm thread a/b/c/d and when they are finished they need to print I'm finished a/b/c/d.

like image 518
njamanjam Avatar asked Jun 06 '13 13:06

njamanjam


4 Answers

Bearing in mind that join and wait do very different things and aren't really related, and also bearing in mind that the example you gave is really, really strange, either choice could potentially be the one you're looking for.

join is probably the easier choice. The thread calling join will wait until the other thread has finished execution. So, each thread in this case will need to hold a reference to the next thread, and it'll call join right before printing "I'm finished". So your class might look like this:

class JoiningThread extends Thread {
    // NOTE: UNTESTED!

    private String name;
    private Thread nextThread;

    public JoiningThread(String name) {
        this(name, null);
    }

    public JoiningThread(String name, Thread other) {
        this.name = name;
        this.nextThread = other;
    }

    public String getName() {
        return name;
    }

    @Override
    public void run() {
        System.out.println("Hello I'm thread ".concat(getName()));
        if (nextThread != null) {
            while(nextThread.isAlive()) {
                try {
                    nextThread.join();
                } catch (InterruptedException e) {
                    // ignore this
                }
            }
        }
        System.out.println("I'm finished ".concat(getName()));
    }
}

And the main method could be:

public static void main(String[] args) {
    Thread d = WaitingThread("d");
    Thread c = WaitingThread("c", d);
    Thread b = WaitingThread("b", c);
    Thread a = WaitingThread("a", b);

    a.start();
    b.start();
    c.start();
    d.start();

    try {
        a.join();
    } catch (InterruptedException e) {}
}

What wait does is suspend the execution of a thread until notify or notifyAll is called. So to implement this idea with wait, you need each thread to hold a reference to the thread before it. The strategy is for the run method to finish with a call to wait, followed by a call to notify the previous thread that execution has finished. So your class might look something like this:

class WaitingThread extends Thread {
    // NOTE: UNTESTED!

    private Thread previousThread;
    private String name;

    public WaitingThread(String name) {
        this(name, null);
    }

    public WaitingThread(String name, Thread other) {
        this.name = name;
        this.previousThread = other;
    }

    public String getName() {
        return name;
    }

    @Override
    public void run() {
        System.out.println("Hello I'm thread ".concat(getName()));
        // Do other things if required

        // Wait to be woken up
        while(true) {
            synchronized(this) {
                try {
                    wait();
                    break;
                } catch (InterruptedException e) {
                    // ignore this
                }
            }
        }

        System.out.println("I'm finished ".concat(getName()));

        // Wake up the previous thread
        if (previousThread != null) {
            synchronized(previousThread) {
                previousThread.notify();
            }
        }
    }
}

And the main method that sets everything up from the main thread might be:

public static void main(String[] args) {
    Thread a = WaitingThread("a");
    Thread b = WaitingThread("b", a);
    Thread c = WaitingThread("c", b);
    Thread d = WaitingThread("d", c);

    a.start();
    b.start();
    c.start();
    d.start();

    while(true) {
        // wake up d once it goes to sleep
        if (d.isAlive()) {
            d.notify();
        }
    }
}
like image 101
Henry Keiter Avatar answered Sep 23 '22 14:09

Henry Keiter


Since you are waiting for the 'other' thread to complete (i.e. finish execution), join() would be the better choice.

The javadoc for join() says simply: Waits for this thread to die.

The mechanism is then relatively simple:

        @Override
        public void run() {
            System.out.println("Hello I'm thread " + getName());
            if (otherThread != null) {
                while (otherThread.isAlive()) {
                    try {
                        otherThread.join();
                    } catch (InterruptedException e) {
                        // ignore
                    }
                }
            }
            System.out.println("I'm finished " + getName());
        }

To explain: you need to have a reference to the otherThread. So a refers to b, b refers to c, c refers to d and d doesn't refer to any otherThread (it's null).

The statement otherThread.join() waits for the other thread to complete. It is wrapped in a loop since join() can throw InterruptedException (though rarely in practise).

Hope this helps, good luck.

like image 27
vikingsteve Avatar answered Sep 23 '22 14:09

vikingsteve


The join() method is used to wait for a thread to complete execution. The join() method of a Thread instance can be used to "join" the start of a thread's execution to the end of another thread's execution so that a thread will not start running until another thread has ended. If join() is called on a Thread instance, the currently running thread will block until the Thread instance has finished executing.

An example of join()

The wait() method is used to wait for a notification to be sent on an object. The two conditions are pretty distinctive.

An example and more explanation of wait()

like image 24
Joetjah Avatar answered Sep 23 '22 14:09

Joetjah


I would do it this way

public class Test1 extends Thread {
    static Object lock = new Object();
    static int n;
    int i;
    String name;

    Test1(String name, int i) {
        this.name = name;
        this.i = i;
    }

    @Override
    public void run() {
    try {
        synchronized (lock) {
            while (i != n) {
                lock.wait();
            }
            System.out.println(name + " started");
            n++;
            lock.notifyAll();
        }
        synchronized (lock) {
            while (i != n - 4) {
                lock.wait();
            }
            System.out.println(name + " finished");
            n++;
            lock.notifyAll();
        }
    } catch (InterruptedException e) {
    }
    }

    public static void main(String[] args) throws Exception {
        new Test1("a", 0).start();
        new Test1("b", 1).start();
        new Test1("c", 2).start();
        new Test1("d", 3).start();
    }
}

output

a started
b started
c started
d started
a finished
b finished
c finished
d finished
like image 25
Evgeniy Dorofeev Avatar answered Sep 23 '22 14:09

Evgeniy Dorofeev