如何让多个线程顺序执行
Posted lqpgjv
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何让多个线程顺序执行相关的知识,希望对你有一定的参考价值。
先说一下为什么会有这样的要求,如果是简单的要求按顺序执行代码,直接一行行写下来就行了。但是接口调用我们一般都放在工作线程里面,而且有时候需要拿一个接口返回的参数去请求另一个接口,这就需要控制线程按某种顺序执行。
方法1:join()
public class A1 extends Thread {
@Override
public void run() {
try {
System.out.println("--- thread A1 start ---");
sleep((long) (Math.random() * 30));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("--- thread A1 end ---");
}
}
public class A2 extends Thread {
@Override
public void run() {
try {
System.out.println("--- thread A2 start ---");
sleep((long) (Math.random() * 30));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("--- thread A2 end ---");
}
}
public class A3 extends Thread {
@Override
public void run() {
try {
System.out.println("--- thread A3 start ---");
sleep((long) (Math.random() * 30));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("--- thread A3 end ---");
}
}
public class OrderTest {
public static void main(String[] args) {
try {
A1 a1 = new A1();
a1.start();
a1.join();
A2 a2 = new A2();
a2.start();
a2.join();
A3 a3 = new A3();
a3.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 控制台输出:
--- thread A1 start ---
--- thread A1 end ---
--- thread A2 start ---
--- thread A2 end ---
--- thread A3 start ---
--- thread A3 end ---
a1.start()
使a1
进入就绪状态,a1
和主线程都可能抢到CPU
执行权,a1.join()
使a1
线程独占CPU
,主线程要等a1
执行完才能执行a2
的初始化和a2.start()
等后续代码。另外,把
a2
的初始化和a2.join()
放在a3
的run()
里面的第一行(即执行a3
的逻辑代码前),把a1
的初始化和a1.join()
放在a2
的run()
里面的第一行,也能让a1
、a2
、a3
顺序执行,效果和上述代码相同。
方法2:wait() & notify()
public class B1 extends Thread{
@Override
public void run() {
synchronized (this){
try {
System.out.println("--- thread B1 start ---");
sleep((long) (Math.random() * 30));
System.out.println("--- thread B1 end ---");
notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class B2 extends Thread {
@Override
public void run() {
B1 b1 = new B1();
b1.start();
synchronized (b1){
try {
b1.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (this){
try {
System.out.println("--- thread B2 start ---");
sleep((long) (Math.random() * 30));
System.out.println("--- thread B2 end ---");
notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class B3 extends Thread {
@Override
public void run() {
B2 b2 = new B2();
b2.start();
synchronized (b2){
try {
b2.wait();
System.out.println("--- thread B3 start ---");
sleep((long) (Math.random() * 30));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("--- thread B3 end ---");
}
}
}
public class OrderTest {
public static void main(String[] args) {
new B3().start();
}
}
// 控制台输出:
--- thread B1 start ---
--- thread B1 end ---
--- thread B2 start ---
--- thread B2 end ---
--- thread B3 start ---
--- thread B3 end ---
需要注意的是,线程
B2
中调用b1.wait()
的时候不是让b1
对象等待,而是让获取到b1
对象同步锁的当前线程等待。这里面的「当前线程」指的就是线程B2
了。线程
B1
中的notify()
,唤醒的是在当前对象上等待的线程(其实这里的notify()
相当于this.notiify()
)。
B2
线程的run()
里面,执行第一个synchronized
代码块的时候,当前线程wait
了,当被唤醒的时候继续执行后续代码(即第二个synchronized
代码块);B3
被唤醒后执行b2.wait()
后面的代码:System.out.println("--- thread B3 start ---");
等。
方法3:线程池
public class OrderTest {
public static void main(String[] args) {
A1 a1 = new A1();
A2 a2 = new A2();
A3 a3 = new A3();
ExecutorService single = Executors.newSingleThreadExecutor();
single.submit(a1);
single.submit(a2);
single.submit(a3);
single.shutdown();
}
}
// 控制台输出:
--- thread A1 start ---
--- thread A1 end ---
--- thread A2 start ---
--- thread A2 end ---
--- thread A3 start ---
--- thread A3 end ---
newSingleThreadExecutor
只包含一个线程,而且可以保证线程按顺序执行。
方法4
最容易想到的办法,在一个线程的run()
里面的结尾处初始化并启动另一个线程(thread.start()
),这个简单就补贴代码了。
以上是关于如何让多个线程顺序执行的主要内容,如果未能解决你的问题,请参考以下文章