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