我们知道在多线程中,线程在启动的时候不是马上去执行任务的,而是由cpu调度让哪一个线程执行,通常情况下多线程的执行顺序是随机的,如果我们想要让线程按照一定的顺序让线程执行,怎么做呢?

1.初见

首先我们先上一段代码,看看执行效果。

1
2
3
4
5
6
7
8
9
private static Thread thread1 = new Thread(()->System.out.println("thread1 开始执行"));
private static Thread thread2 = new Thread(()->System.out.println("thread2 开始执行"));
private static Thread thread3 = new Thread(()->System.out.println("thread3 开始执行"));

public static void main(String[] args) {
thread1.start();
thread2.start();
thread3.start();
}

执行结果如图所示:
如图示
从代码运行结果看,线程执行的顺序是随机的,我们无法保证线程按照特定的顺序执行,线程启动之后处于就绪状态,等待CPU调度执行,也就是说如果不做处理话,我们是无法控制的。

2.相恋

2.1 设置线程优先级

线程的执行除了CPU调度外,还有一个因素就是每个线程的优先级,线程的级别有1-10个等级,级别越高表示线程越有可能拿到CPU时间片,但是并不是优先级越高的线程就一定比优先级低的线程更早获得CPU时间片执行任务呢,按但是否定的,我们只能说优先级高的线程更有可能获取的执行权,如果说优先级高的进入了等待,那么优先级低的线程就会执行,如果几个线程都处于就组状态,那毫无疑问优先级高的线程就会先执行。

1
2
3
4
5
6
7
8
9
10
11
private static Thread thread1 = new Thread(()->System.out.println("thread1 开始执行"));
private static Thread thread2 = new Thread(()->System.out.println("thread2 开始执行"));
private static Thread thread3 = new Thread(()->System.out.println("thread3 开始执行"));
public static void main(String[] args) {
thread3.setPriority(Thread.MAX_PRIORITY);
thread2.setPriority(Thread.NORM_PRIORITY);
thread1.setPriority(Thread.MIN_PRIORITY);
thread1.start();
thread2.start();
thread3.start();
}

如图示

2.2 Thread.join()

我们Thread.join()方法就是让主线程等待,新线程执行完了后再继续执行主线程,让我们来看一下Thread.join()方法的源码吧
源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public final void join() throws InterruptedException {
join(0);
}

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;
}
}
}

源码很清晰的告诉我们,当我们调用join()方法后,后调用join(long millis),在millis == 0的情况下,如果当前线程是存活的,就让当前线程等待,让新线程继续执行知道死亡,知道原理后就来实现下代码喔。

1
2
3
4
5
6
7
8
9
10
private static Thread thread1 = new Thread(()->System.out.println("thread1 开始执行"));
private static Thread thread2 = new Thread(()->System.out.println("thread2 开始执行"));
private static Thread thread3 = new Thread(()->System.out.println("thread3 开始执行"));
public static void main(String[] args) throws InterruptedException {
thread1.start();
thread1.join();
thread2.start();
thread2.join();
thread3.start();
}

2.3 Executors.newSingleThreadExecutor()

Executors.newSingleThreadExecutor()就是创建一个只有一个线程线程池,让我们看了一个源码吧

1
2
3
4
5
6
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}

我们可以看到Executors.newSingleThreadExecutor()实际上是创建了一个单线程的线程池,并且维护了一个任务队列,我们知道队列的特点就是FIFO(先进先出),而且线程池每次只能执行一个任务线程,其余的线程实际上放到new LinkedBlockingQueue()这个队列里等待CPU调度,当第一个线程执行完了后,线程池就会从队列取下一个任务线程来执行,以此类推,从而保证了线程的执行顺序,来看看代码怎么实现的吧

1
2
3
4
5
6
7
8
9
10
private static Thread thread1 = new Thread(()->System.out.println("thread1 开始执行"));
private static Thread thread2 = new Thread(()->System.out.println("thread2 开始执行"));
private static Thread thread3 = new Thread(()->System.out.println("thread3 开始执行"));
private static ExecutorService service = Executors.newSingleThreadExecutor();
public static void main(String[] args) throws InterruptedException {
service.execute(thread1);
service.execute(thread2);
service.execute(thread3);
service.shutdown();
}

婚恋

以上就是控制多线程执行顺序方法,有什么不对欢迎指正喔。