登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

love3400wind的blog

like

 
 
 

日志

 
 
 
 

[Java多线程]ABC三个线程顺序输出的问题  

2013-12-07 22:29:41|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

大概的问题是这样的:

有A,B,C三个线程, A线程输出A, B线程输出B, C线程输出C

要求, 同时启动三个线程, 按顺序输出ABC, 循环10次

这是一个多线程协同的问题, 本身多线程是没有执行顺序的, 顺序不一定, Java在concurrent里面提供了多线程同步的支持

使用ReentrantLock来解决, 还有个state整数用来判断轮到谁执行了

复制代码
 1 import java.util.concurrent.locks.Lock;
 2 import java.util.concurrent.locks.ReentrantLock;
 3 
 4 public class ABC {
 5     private static Lock lock = new ReentrantLock();//通过JDK5中的锁来保证线程的访问的互斥
 6     private static int state = 0;
 7     
 8     static class ThreadA extends Thread {
 9         @Override
10         public void run() {
11             for (int i = 0; i < 10;) {
12                 lock.lock();
13                 if (state % 3 == 0) {
14                     System.out.print("A");
15                     state++;
16                     i++;
17                 }
18                 lock.unlock();
19             }
20         }
21     }
22     
23     static class ThreadB extends Thread {
24         @Override
25         public void run() {
26             for (int i = 0; i < 10;) {
27                 lock.lock();
28                 if (state % 3 == 1) {
29                     System.out.print("B");
30                     state++;
31                     i++;
32                 }
33                 lock.unlock();
34             }
35         }
36     }
37     
38     static class ThreadC extends Thread {
39         @Override
40         public void run() {
41             for (int i = 0; i < 10;) {
42                 lock.lock();
43                 if (state % 3 == 2) {
44                     System.out.print("C");
45                     state++;
46                     i++;
47                 }
48                 lock.unlock();
49             }
50         }
51     }
52     
53     public static void main(String[] args) {
54         new ThreadA().start();
55         new ThreadB().start();
56         new ThreadC().start();
57     }
58     
59 }
复制代码

使用lock来保证只有一个线程在输出操作, 要保证了state不会被两个线程同时修改, 思路简单

还可以使用condition, condition的效率可能会更高一些, await会释放lock锁, condition的await和signal与object的wait和notify方法作用类似

复制代码
 1 import java.util.concurrent.locks.Condition;
 2 import java.util.concurrent.locks.Lock;
 3 import java.util.concurrent.locks.ReentrantLock;
 4 
 5 public class ABC2 {
 6     private static Lock lock = new ReentrantLock();
 7     private static int count = 0;
 8     private static Condition A = lock.newCondition();
 9     private static Condition B = lock.newCondition();
10     private static Condition C = lock.newCondition();
11     
12     static class ThreadA extends Thread {
13 
14         @Override
15         public void run() {
16             lock.lock();
17             try {
18                 for (int i = 0; i < 10; i++) {
19                     while (count % 3 != 0)
20                         A.await(); // 会释放lock锁
21                     System.out.print("A");
22                     count++;
23                     B.signal(); // 唤醒相应线程
24                 }
25             } catch (InterruptedException e) {
26                 e.printStackTrace();
27             } finally {
28                 lock.unlock();
29             }
30         }
31         
32     }
33     
34     static class ThreadB extends Thread {
35 
36         @Override
37         public void run() {
38             lock.lock();
39             try {
40                 for (int i = 0; i < 10; i++) {
41                     while (count % 3 != 1)
42                         B.await();
43                     System.out.print("B");
44                     count++;
45                     C.signal();
46                 }
47             } catch (InterruptedException e) {
48                 e.printStackTrace();
49             } finally {
50                 lock.unlock();
51             }
52         }
53         
54     }
55     
56     static class ThreadC extends Thread {
57 
58         @Override
59         public void run() {
60             lock.lock();
61             try {
62                 for (int i = 0; i < 10; i++) {
63                     while (count % 3 != 2)
64                         C.await();
65                     System.out.println("C");
66                     count++;
67                     A.signal();
68                 }
69             } catch (InterruptedException e) {
70                 e.printStackTrace();
71             } finally {
72                 lock.unlock();
73             }
74         }
75         
76     }
77     
78     public static void main(String[] args) throws InterruptedException {
79         new ThreadA().start();
80         new ThreadB().start();
81         ThreadC threadC = new ThreadC();
82         threadC.start();
83         threadC.join();
84         System.out.println(count);
85     }
86 }
复制代码

使用信号量也可以, 这个思路最简单, 整个代码也比较简洁

复制代码
 1 import java.util.concurrent.Semaphore;
 2 
 3 public class ABC3 {
 4     private static Semaphore A = new Semaphore(1);
 5     private static Semaphore B = new Semaphore(1);
 6     private static Semaphore C = new Semaphore(1);
 7     
 8     static class ThreadA extends Thread {
 9 
10         @Override
11         public void run() {
12             try {
13                 for (int i = 0; i < 10; i++) {
14                     A.acquire();
15                     System.out.print("A");
16                     B.release();
17                 }
18             } catch (InterruptedException e) {
19                 e.printStackTrace();
20             }
21         }
22         
23     }
24     
25     static class ThreadB extends Thread {
26 
27         @Override
28         public void run() {
29             try {
30                 for (int i = 0; i < 10; i++) {
31                     B.acquire();
32                     System.out.print("B");
33                     C.release();
34                 }
35             } catch (InterruptedException e) {
36                 e.printStackTrace();
37             }
38         }
39         
40     }
41     
42     static class ThreadC extends Thread {
43 
44         @Override
45         public void run() {
46             try {
47                 for (int i = 0; i < 10; i++) {
48                     C.acquire();
49                     System.out.println("C");
50                     A.release();
51                 }
52             } catch (InterruptedException e) {
53                 e.printStackTrace();
54             }
55         }
56         
57     }
58     
59     public static void main(String[] args) throws InterruptedException {
60         B.acquire(); C.acquire(); // 开始只有A可以获取, BC都不可以获取, 保证了A最先执行
61         new ThreadA().start();
62         new ThreadB().start();
63         new ThreadC().start();
64     }
65 }
复制代码

注意:

lock是需要lock所有者去释放的, 即谁lock, 谁释放, 不可以跨线程, 会报java.lang.IllegalMonitorStateException;

semaphore是没有所有者的说法, 可以跨线程释放和获取.

 

这是一道java笔试题, 多线程的问题现在越来越多的出现在笔试中, 要好好学习.

水平有限, 如有错漏, 请指针, 欢迎拍砖, 共同探讨!

参考文献:

  1. 深入浅出Java Concurrency: http://www.blogjava.net/xylz/archive/2010/07/08/325587.html

jdk1.4实现:
/**
 * @author heyunxia (love3400wind@163.com)
 * @version 1.0
 * @since 2015-10-26 上午9:53
 */
public class ThreadABC {
    public static void main(String[] args) {
        final ABC abc = new ABC();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    abc.printA();
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    abc.printB();
                }
            }
        }).start();


        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    abc.printC();
                }
            }
        }).start();
    }


    static class ABC {
        private String flag = "A";

        public synchronized void printA() {
            while (!"A".equals(flag)) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.print("A");
            this.flag = "B";
            this.notifyAll();
        }

        public synchronized void printB() {
            while (!"B".equals(flag)) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.print("B");
            this.flag = "C";
            this.notifyAll();
        }

        public synchronized void printC() {
            while (!"C".equals(flag)) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.print("C");
            System.out.println();
            this.flag = "A";
            this.notifyAll();
        }
    }
}
  评论这张
 
阅读(5713)| 评论(0)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018