#### 1、背景
最近参加某某公司的Java实习生面试,面试官提出了一个多线程编程的笔试题,当时脑子一热,不管三七二十一,就虾肝了一番,最后把自己都整糊涂了。今天思考了下,发现确实挺简单的。
#### 2、测试题目
如果有三个线程名字为:"load","process","store" 。写一个多线程实现三个线程间有序执行模拟处理数据的全过程。依次在控制台输出 load,process,store ... 这个过程持续三次
执行完毕时打印 "over!!!",表示执行结束。
**示例:**
```
load,process,store,load,process,store,load,process,store over!!!
```
#### 3、思路
首先这道题主要考察线程的执行顺序和线程循环执行次数。
##### 3.1、线程的执行顺序
线程的执行顺序好说,我们可以用join()方法让一个线程充分运行完之后再启动另一个线程,以此类推,就可以实现按指定顺序执行线程了。但问题来了,join()方法需要线程终结之后才能返回,这样就不能重复利用一个线程了,所以这个方法pass掉。我们的目的是想让线程运行时运行,不运行时阻塞或等待,等到所有的打印逻辑都实现了之后再终结,所以就得用到wait()方法和notifyAll()方法,wait方法可以是一个线程从运行态转变为等待态,而notifyAll()可以唤醒所有线程。而这两个方法使用的前提是获得到锁,所以还得用到synchronized关键字。这样就可以利用线程的阻塞和等待来实现线程的执行顺序。
##### 3.2、线程的循环执行次数
控制线程的循环执行次数,可以使用一个标识变量(boolean变量就可以)来控制循环次数,如果循环次数小于指定数值,就致其为true,否则为false。
#### 4、具体代码实现
```java
import java.util.concurrent.TimeUnit;
/**
* @author miantiao
* @time 2020年4月9日 上午7:52:17
*/
public class ThreadTest {
//控制打印数量和线程打印顺序的计数器变量
static int count = 0;
//声明需要加锁的对象
static final Object obj = new Object();
//控制线程终止的标识变量
static boolean flag = true;
//定义load线程。打印的顺序位为1
Thread load = new Thread(new Runnable() {
@Override
public void run() {
while (flag) {
synchronized (obj) {
if (count % 3 == 0) {//第一位打印
System.out.print("load,");
count++;
if(count>8)
flag = false;//当count>8时,则说明已经每个线程分别打印了3次,所以将flag致为false,结束线程
obj.notifyAll();
} else
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
//定义process线程。打印的顺序位为2
Thread process = new Thread(new Runnable() {
@Override
public void run() {
while (flag) {
synchronized (obj) {
if (count % 3 == 1) {
System.out.print("process,");
count++;
if(count>8)
flag = false;
obj.notifyAll();
} else
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
//定义store线程。打印的顺序位为3
Thread store = new Thread(new Runnable() {
@Override
public void run() {
while (flag) {
synchronized (obj) {
if (count % 3 == 2) {
System.out.print("store,");
count++;
if(count>8)
flag = false;
obj.notifyAll();
} else
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
/**
* 启动三个线程
*/
public void fun() {
load.start();
process.start();
store.start();
}
public static void main(String[] args) throws InterruptedException {
ThreadTest tt = new ThreadTest();
tt.fun();
//等待3个线程充分运行
Thread.sleep(10);
System.out.println("over!!!");
}
}
```
```
打印结果为:load,process,store,load,process,store,load,process,store,over!!!
```

控制线程运行顺序及循环运行次数