使用join()和wait()线程java

时间:2013-06-06 13:27:55

标签: java multithreading

我需要制作一系列线程。他们需要按照这样的顺序开始:

A then B then C and finally D.

当D完成时,C可以完成B,然后是A。

在这种情况下,最好使用join()个帖子还是wait()?为什么?

我的帖子需要启动并打印消息Hello I'm thread a/b/c/d,完成后需要打印I'm finished a/b/c/d

4 个答案:

答案 0 :(得分:9)

请记住,joinwait做了非常不同的事情并且没有真正相关,并且还要记住你给出的例子真的很奇怪,要么选择可能是你正在寻找的那个。

join可能是更容易的选择。调用join的线程将一直等到另一个线程完成执行。因此,在这种情况下,每个线程都需要保存对 next 线程的引用,并且在打印“我完成”之前它将调用join。所以你的课可能是这样的:

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()));
    }
}

主要方法可能是:

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) {}
}

wait做的是暂停执行某个线程,直到调用notifynotifyAll为止。因此,要使用wait实现此想法,您需要每个线程在之前保存对线程的引用。策略是run方法完成对wait的调用,然后调用notify执行完成的前一个线程。所以你的课可能看起来像这样:

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();
            }
        }
    }
}

从主线程设置所有内容的main方法可能是:

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();
        }
    }
}

答案 1 :(得分:6)

由于您正在等待“其他”线程完成(即完成执行),join()将是更好的选择。

join()的javadoc简单地说:等待此线程死亡。

这个机制相对简单:

        @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());
        }

要解释:您需要引用otherThread。因此a引用bb引用cc引用dd引用otherThread任何otherThread.join()(它为空)。

语句join()等待另一个线程完成。它被包装在循环中,因为InterruptedException可以抛出{{1}}(虽然很少在实践中)。

希望这会有所帮助,祝你好运。

答案 2 :(得分:3)

join()方法用于等待线程完成执行。 Thread实例的join()方法可用于将线程执行的开始“连接”到另一个线程的执行结束,这样在另一个线程结束之前线程不会开始运行。如果在Thread实例上调用join(),则当前运行的线程将阻塞,直到Thread实例完成执行。

An example of join()

wait()方法用于等待在对象上发送通知。这两个条件非常独特。

An example and more explanation of wait()

答案 3 :(得分:1)

我会这样做

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();
    }
}

输出

a started
b started
c started
d started
a finished
b finished
c finished
d finished