使线程具有有序性:
线程在运行时多个线程之间执行的时机是无序的,下面通过改造代码实现运行具有有序性:
1 /**
2 * 线程类
3 */
4 public class MyThread extends Thread {
5 private Object lock;
6 private String showChar;
7 private int showNumPosition;
8 private int printCount = 0;//统计打印了几个字母
9 volatile private static int addNumber = 1;
10
11 //构造
12 public MyThread(Object lock, String showChar, int showNumPosition) {
13 this.lock = lock;
14 this.showChar = showChar;
15 this.showNumPosition = showNumPosition;
16 }
17
18 @Override
19 public void run() {
20 try {
21 synchronized(lock) {
22 while(true) {
23 if(addNumber % 3 == showNumPosition) {
24 System.out.println("ThreadName = " + Thread.currentThread().getName()
25 + " runCount" + addNumber + " " + showChar);
26 lock.notifyAll();
27 addNumber++;
28 printCount++;
29 if(printCount == 3) {
30 break;
31 }
32 }else {
33 lock.wait();
34 }
35 }
36 }
37 } catch (InterruptedException e) {
38 e.printStackTrace();
39 }
40 }
41 }
1 /**
2 * 测试,线程有序执行打印
3 */
4 public class Run {
5 /**
6 * 线程执行分析:
7 * 当三个线程启动后,如果是b和c线程拿到锁,则会进入到else中线程等待
8 * printCount为每个线程私有的变量,也就是每个线程都会执行三次后不再循环
9 * addNumber为线程共享变量,三个线程分别运行结束之后addNumber累加
10 * 运行结果如下:
11 * ThreadName = Thread-0 runCount1 A
12 * ThreadName = Thread-1 runCount2 B
13 * ThreadName = Thread-2 runCount3 C
14 * ThreadName = Thread-0 runCount4 A
15 * ThreadName = Thread-1 runCount5 B
16 * ThreadName = Thread-2 runCount6 C
17 * ThreadName = Thread-0 runCount7 A
18 * ThreadName = Thread-1 runCount8 B
19 * ThreadName = Thread-2 runCount9 C
20 *
21 * 可以看到第一个运行的是a线程,因为a线程构造参数showNumPosition正好就是初始的addNumber%3的值
22 * 此时运行代码后输出:ThreadName = Thread-0 runCount1 A
23 * 全局addNumber修改为2,a线程中的printCount变成1,当A线程再次执行循环时,进入else代码块,线程等待
24 *
25 * 此时如果时线程c拿到锁,则线程c会进入else块,线程等待,然后线程b拿到锁,由于当前线程a修改了全局addNumber,
26 * 所有线程b在进入循环判断时,构造参数showNumPosition正好就是初始的addNumber%3的值
27 * 此时运行代码后输出:ThreadName = Thread-1 runCount2 B
28 * 并唤醒其他线程,此时a和c线程被唤醒,争抢锁
29 * 全局addNumber修改为3,b线程中的printCount变成1,当c线程再次执行循环时,进入else代码块,线程等待
30 *
31 * 此时如果是a线程获得锁,则会进入else块,线程等待,然后c线程拿到锁,由于当前线程b修改了全局addNumber,
32 * 所有线程c在进入循环判断时,构造参数showNumPosition正好就是初始的addNumber%3的值
33 * 此时运行代码后输出:ThreadName = Thread-2 runCount3 C
34 * 并唤醒其他线程,此时a和b线程被唤醒,争抢锁
35 * 全局addNumber修改为4,c线程中的printCount变成1,当c线程再次执行循环时,进入else代码块,线程等待
36 *
37 * 以此类推,当线程中的私有变量printCount为3后,线程退出循环。
38 */
39 public static void main(String[] args) {
40 Object lock = new Object();
41 MyThread a = new MyThread(lock, "A", 1);
42 MyThread b = new MyThread(lock, "B", 2);
43 MyThread c = new MyThread(lock, "C", 0);
44 a.start();
45 b.start();
46 c.start();
47 }
48 }