使線程具有有序性:
線程在運行時多個線程之間執行的時機是無序的,下面通過改造代碼實現運行具有有序性:
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 }
