我需要制作线程序列。他们需要按如下顺序开始:
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
。
我需要制作线程序列。他们需要按如下顺序开始:
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
。
记住这一点join
并wait
做非常不同的事情并且并不真正相关,并且还要记住你给出的例子真的非常奇怪,任何一个选择都可能是你正在寻找的那个。
join
可能是更容易的选择。线程调用join
将等到另一个线程完成执行。因此,在这种情况下,每个线程都需要保存对下一个线程的引用,并且它会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
是暂停线程的执行,直到notify
或被notifyAll
调用。所以要实现这个想法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();
}
}
}
由于您正在等待“其他”线程完成(即完成执行),join()
因此将是更好的选择。
javadocjoin()
简单地说:等待这个线程死亡。
该机制相对简单:
@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
指的是b
,b
指的是c
,c
指的是d
并且d
不指任何otherThread
(它是空的)。
该语句otherThread.join()
等待另一个线程完成。它被包裹在一个循环中,因为join()
可以抛出InterruptedException
(尽管在实践中很少)。
希望这有帮助,祝你好运。
该join()
方法用于等待线程完成执行。Thread 实例的join()
方法可用于将线程执行的开始“连接”到另一个线程执行的结束,这样一个线程在另一个线程结束之前不会开始运行。如果join()
在 Thread 实例上调用,则当前正在运行的线程将阻塞,直到 Thread 实例完成执行。
该wait()
方法用于等待在对象上发送通知。这两个条件非常有特色。
我会这样做
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