[Java多线程]ABC三个线程顺序输出的问题
大概的问题是这样的:
有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笔试题, 多线程的问题现在越来越多的出现在笔试中, 要好好学习.
水平有限, 如有错漏, 请指针, 欢迎拍砖, 共同探讨!
参考文献:
- 深入浅出Java Concurrency: http://www.blogjava.net/xylz/archive/2010/07/08/325587.html
以上是 [Java多线程]ABC三个线程顺序输出的问题 的全部内容, 来源链接: utcz.com/z/390752.html