对于这个题目我们应该使用join()方法来解决。
join()作用:等待线程对象销毁。使所属的线程对象x正常执行run()方法中的任务,而使其他线程进行无期限的阻塞,等待线程x销毁后再继续执行其他线程的代码。
- 没有使用join()方法t1 t2 t3 线程的执行:
package com.learn.joinTest;
/**
* t1 t2 t3 三个线程,使得t2在t1执行完之后执行,t3在t2执行完之后执行
*/
public class TestJoin {
public static void main(String[] args) throws InterruptedException {
ThreadT t1 = new ThreadT();
ThreadT t2 = new ThreadT();
ThreadT t3 = new ThreadT();
t1.setName("我是t1");
t2.setName("我是t2");
t3.setName("我是t3");
t1.start();
// t1.join();
t2.start();
// t2.join();
t3.start();
}
}
class ThreadT extends Thread{
@Override
public void run() {
super.run();
System.out.println("线程名称为:"+Thread.currentThread().getName());
}
}
可看到t1 t2 t3的执行是随机的。
- 使用join()方法之后t1 t2 t3 线程的执行
package com.learn.joinTest;
/**
* t1 t2 t3 三个线程,使得t2在t1执行完之后执行,t3在t2执行完之后执行
*/
public class TestJoin {
public static void main(String[] args) throws InterruptedException {
ThreadT t1 = new ThreadT();
ThreadT t2 = new ThreadT();
ThreadT t3 = new ThreadT();
t1.setName("我是t1");
t2.setName("我是t2");
t3.setName("我是t3");
t1.start();
t1.join();
t2.start();
t2.join();
t3.start();
}
}
class ThreadT extends Thread{
@Override
public void run() {
super.run();
System.out.println("线程名称为:"+Thread.currentThread().getName());
}
}
此结果符合题目要求。
-----------------------扩展题目--------------------------
join(long)和sleep(long)的区别是什么呢?
因为方法join(long)的功能在内部是使用wait(long)方法来实现的,所以我们来讨论wait(long)和sleep(long)的区别。
join(long)的源码:
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
- wait方法:会释放锁,常被用于线程间的交互。
- sleep方法:一直持有锁,常被用于暂停执行。