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

java

大概的问题是这样的:

有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

以上是 [Java多线程]ABC三个线程顺序输出的问题 的全部内容, 来源链接: utcz.com/z/390752.html

回到顶部