在面试的时候可能会被问到高并发的东西,有这么一道经典的面试题:
怎么控制多线程的顺序 答案有两个
- 1、Thread.join();
- 2、 ExecutorService executorService = Executors.newSingleThreadExecutor();
我们来编写一个程序:
public class sequentialControl {
public static void main(String[] args) {
/**
* 创建三个线程
*/
Thread thread1 = new Thread(){
@Override
public void run() {
System.out.println("thread1 !!!");
}
};
Thread thread2 = new Thread(){
@Override
public void run() {
System.out.println("thread2 !!!");
}
};
Thread thread3 = new Thread(){
@Override
public void run() {
System.out.println("thread3 !!!");
}
};
/**
* 代码中顺序执行三个线程,观察执行顺序
*/
thread1.start();
thread2.start();
thread3.start();
}
}
代码输出的顺序是不可控制的,如果输出时顺序,那么请多输出几次或者多创建几个线程后执行输出,可能你的cpu的运行运算速度超级快,看到的结果一直都是顺序的,在这里给你解释一下现成的执行原理:
Java中的线程是通过cpu时间片的轮训来实现的,也就是说单核cpu同一时间只会执行一个线程中的指令,java多线程是通过线程的轮流切换并分配处理器执行的时间来实现的。
此时如果想要控制线程的顺序执行,首先使用第一种方法:join
join的使用办法非常简单。
/**
* 线程顺序执行方法一
*/
thread1.start();
thread1.join();
thread2.start();
thread2.join();
thread3.start();
thread3.join();
通过每个线程调用join方法来保证现成的顺序执行。可能直接说出来通过join可以保证线程的顺序执行没有什么说服力,下面我们点进源码中看一下原因。
public final void join() throws InterruptedException {
join(0); // 通过外部可访问的join无参方法调用内部的带参方法
}
//millis参数的意义为当前线程停止运行,并处于等待状态的等待时间
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
//线程等待时间不可小于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;
}
}
}
这里有一个需要注意的地方,就是线程的等待,这个线程,指的是主线程,thread1在执行的过程中,停止了主线程的执行状态,主线程不在继续执行,其他线程自然没办法继续执行。所以就控制住了线程的执行顺序。
上面的是第一种让线程顺序执行的办法,下面来说一下第二中顺序执行的方法
static ExecutorService executorService = Executors.newSingleThreadExecutor();
/**
* 线程顺序执行二
* main方法中执行
*/
executorService.submit(thread1);
executorService.submit(thread2);
executorService.submit(thread3);
executorService.shutdown();
jdk5中提出的单线程池,通过把线程放入单线程池中,单线程池可以想象成一个先进先出的队列。