多线程-使线程具有有序性
使线程具有有序性:
线程在运行时多个线程之间执行的时机是无序的,下面通过改造代码实现运行具有有序性:
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 }