多线程-使线程具有有序性

使线程具有有序性:

线程在运行时多个线程之间执行的时机是无序的,下面通过改造代码实现运行具有有序性:

 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 }

 

posted @ 2018-09-04 16:20  为你编程  阅读(2223)  评论(0编辑  收藏  举报