方案有四:
- 【抛弃系列,最low】【线程 t1】代码执行完,调用【线程t2】的start()方法,【t2】执行完调用【线程t3】的start()方法;
- 使用线程间通信,3个线程使用同一把锁,【线程t1】执行完后,使用 JUC 中
signal()/signalAll() 方法唤醒【线程t2】,以此类推; - 【推荐使用】 使用线程为我们提供的
join() 方法; - 使用 LockSupport 类的
park() 和 unpark(Thread thread) 方法。
备注: ??代码中使用 sleep() 也是为了更方便复现问题
方案一
??【抛弃系列,最low】方案一是最 low 的一种方式,不做介绍,不建议使用!!!【最终执行顺序:main > t1 > t2 > t3 】
public class SortThread1 {
public static void main(String[] args) throws InterruptedException {
Thread t3 = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName() + "线程执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "t3");
Thread t2 = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "线程执行完毕");
t3.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "t2");
Thread t1 = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName() + "线程执行完毕");
t2.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"t1");
t1.start();
System.out.println("main 主线程");
}
}
方案二
??采用线程间通信 。三个线程同时启动,使用一把锁。三个线程 t1,t2,t3,按顺序执行,线程 t1 执行完成后,通知线程 t2 ,t2 获取锁后,继续执行,以此类推。【最终执行顺序:t1 > t2 > t3 > main】
public class SortThread2 {
private volatile static int threadNo = 1;
public static void main(String[] args) throws InterruptedException {
Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();
Condition condition4 = lock.newCondition();
Thread t1 = new Thread(() -> {
lock.lock();
try {
while (threadNo != 1) {
condition1.await();
}
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName() + "线程执行完毕");
threadNo = 2;
condition2.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}, "t1");
Thread t2 = new Thread(() -> {
lock.lock();
try {
while (threadNo != 2) {
condition2.await();
}
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "线程执行完毕");
threadNo = 3;
condition3.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}, "t2");
Thread t3 = new Thread(() -> {
lock.lock();
try {
while (threadNo != 3) {
condition3.await();
}
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName() + "线程执行完毕");
threadNo = 4;
condition4.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}, "t3");
t3.start();
t2.start();
t1.start();
lock.lock();
while (threadNo != 4) {
condition4.await();
}
System.out.println("main主线程");
}
}
方案三
??【推荐使用】使用线程为我们提供的 join() 方法。join() 方法会等待当前线程,join(0)则会一直等待线程死亡。join() 和 join(long millis) 方法源码 ,如下图所示:
【最终执行顺序:t1 > t2 > t3 > main】
public class SortThread3 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName() + "线程执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
}
},"t1");
Thread t2 = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "线程执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "t2");
Thread t3 = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName() + "线程执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "t3");
t1.start();
t1.join();
t2.start();
t2.join();
t3.start();
t3.join();
System.out.println("main主线程");
}
}
方案四
??LockSupport.park() 阻塞当前线程,LockSupport.unpark(Thread thread) 唤醒指定线程。LockSupport 属于偏底层方法,了解 LockSupport 的可以来这里查看一下【线程六大状态图:https://blog.csdn.net/lzb348110175/article/details/103579044】,更多请自行百度。【最终执行顺序:t1 > t2 > t3 > main】
public class SortThread4 {
private static Thread main = Thread.currentThread();
public static void main(String[] args) throws InterruptedException {
Thread t3 = new Thread(() -> {
try {
LockSupport.park();
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName() + "线程执行完毕");
LockSupport.unpark(main);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "t3");
Thread t2 = new Thread(() -> {
try {
LockSupport.park();
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "线程执行完毕");
LockSupport.unpark(t3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "t2");
Thread t1 = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName() + "线程执行完毕");
LockSupport.unpark(t2);
} catch (InterruptedException e) {
e.printStackTrace();
}
},"t1");
t1.start();
t2.start();
t3.start();
LockSupport.park(t1);
System.out.println("main主线程");
}
}
博主写作不易,加个关注呗
求关注、求点赞,加个关注不迷路 ヾ(?°?°?)ノ゙
我不能保证所写的内容都正确,但是可以保证不复制、不粘贴。保证每一句话、每一行代码都是亲手敲过的,错误也请指出,望轻喷 Thanks?(・ω・)ノ
|