多线程循环打印ABC

主要是利用线程的wait()和notify()来实现

public class MyThread implements Runnable {
    private String name;
    private Object prev;
    private Object mine;
    
    private MyThread(String name,Object prev,Object mine){
        this.name = name;
        this.prev = prev;
        this.mine = mine;
    }
    

    @Override
    public void run() {
        int count = 10;
        while(count > 0){
            synchronized (prev) {
                synchronized (mine) {
                    System.out.println(name);
                    count--;
                    mine.notify();
                }
                
                try {
                    prev.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
            }
        }
        
    }
    
    
    public static void main(String[] args) {
        Object a = new Object();
        Object b = new Object();
        Object c = new Object();
        MyThread pa = new MyThread("A", c, a);
        MyThread pb = new MyThread("B", a, b);
        MyThread pc = new MyThread("C", b, c);
        new Thread(pa).start();
        new Thread(pb).start();
        new Thread(pc).start();
        
    }

}

整理下程序的思路:因3个线程要按照顺序打印ABC,那么应该是ThreadA->ThreadB->ThreadC->ThreadA如此循环,当运行ThreadA时,prev对象是c,mine对象是a,打印A,然后唤醒线程a,最后让当前线程c等待,则ThreadA进入等待(注意此时调用的prev.wait()虽然让线程进入了等待,但同时也释放了对象的锁,其他线程可以访问此同步方法)。ThreadB的prev对象是a,mine对象是b,打印B;而ThreadC的prev对象是b,mine对象是c;其实这种方式不一定能完全保证是ABC的顺序输出,因为看程序,B线程在等待a对象的锁,获取a的锁才能继续向下进行,而C线程在如果抢先运行的话,b的锁是不需要等待的,则直接等待a的锁,在ThreadA运行完毕释放锁后,若C线程率先获取a的锁的话,那么打印顺序就会遭到改变。所以若要让线程A、B、C按照顺序执行的话,一定要让3个线程按照顺序执行。更改程序为:

 1 public class MyThread implements Runnable {
 2     private String name;
 3     private Object prev;
 4     private Object mine;
 5     
 6     private MyThread(String name,Object prev,Object mine){
 7         this.name = name;
 8         this.prev = prev;
 9         this.mine = mine;
10     }
11     
12 
13     @Override
14     public void run() {
15         int count = 10;
16         while(count > 0){
17             synchronized (prev) {
18                 synchronized (mine) {
19                     System.out.println(name);
20                     count--;
21                     try {
22                         Thread.sleep(1);
23                     } catch (InterruptedException e) {
24                         e.printStackTrace();
25                     }
26                     mine.notify();
27                 }
28                 
29                 try {
30                     prev.wait();
31                 } catch (InterruptedException e) {
32                     e.printStackTrace();
33                 }
34                 
35             }
36         }
37         
38     }
39     
40     
41     public static void main(String[] args) {
42         Object a = new Object();
43         Object b = new Object();
44         Object c = new Object();
45         MyThread pa = new MyThread("A", c, a);
46         MyThread pb = new MyThread("B", a, b);
47         MyThread pc = new MyThread("C", b, c);
48         try {
49             new Thread(pa).start();
50             Thread.sleep(10);
51             new Thread(pb).start();
52             Thread.sleep(10);
53             new Thread(pc).start();
54         } catch (InterruptedException e) {
55             e.printStackTrace();
56         }
57         
58     }
59 
60 }

这样就能真正的实现,第一遍运行顺序为ThreadA打印A,然后ThreadA等待->ThreadB打印B,然后B等待->ThreadC打印C,然后C等待并唤醒A;以此循环打印了。

文章思路不是很清晰,主要还是学习别人写的东西,转化成自己能够理解的语言。努力学习中!

posted @ 2017-10-20 15:55  晴朗依旧  阅读(1198)  评论(0编辑  收藏  举报