大概的问题是这样的:
有A,B,C三个线程, A线程输出A, B线程输出B, C线程输出C
要求, 同时启动三个线程, 按顺序输出ABC, 循环10次
这是一个多线程协同的问题, 本身多线程是没有执行顺序的, 顺序不一定, Java在concurrent里面提供了多线程同步的支持
使用ReentrantLock来解决, 还有个state整数用来判断轮到谁执行了
1 importjava.util.concurrent.locks.Lock;2 importjava.util.concurrent.locks.ReentrantLock;3
4 public classABC {5 private static Lock lock = new ReentrantLock();//通过JDK5中的锁来保证线程的访问的互斥
6 private static int state = 0;7
8 static class ThreadA extendsThread {9 @Override10 public voidrun() {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 extendsThread {24 @Override25 public voidrun() {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 extendsThread {39 @Override40 public voidrun() {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 voidmain(String[] args) {54 newThreadA().start();55 newThreadB().start();56 newThreadC().start();57 }58
59 }
使用lock来保证只有一个线程在输出操作, 要保证了state不会被两个线程同时修改, 思路简单
还可以使用condition, condition的效率可能会更高一些, await会释放lock锁, condition的await和signal与object的wait和notify方法作用类似
1 importjava.util.concurrent.locks.Condition;2 importjava.util.concurrent.locks.Lock;3 importjava.util.concurrent.locks.ReentrantLock;4
5 public classABC2 {6 private static Lock lock = newReentrantLock();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 extendsThread {13
14 @Override15 public voidrun() {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 extendsThread {35
36 @Override37 public voidrun() {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 extendsThread {57
58 @Override59 public voidrun() {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) throwsInterruptedException {79 newThreadA().start();80 newThreadB().start();81 ThreadC threadC = newThreadC();82 threadC.start();83 threadC.join();84 System.out.println(count);85 }86 }
使用信号量也可以, 这个思路最简单, 整个代码也比较简洁
1 importjava.util.concurrent.Semaphore;2
3 public classABC3 {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 extendsThread {9
10 @Override11 public voidrun() {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 extendsThread {26
27 @Override28 public voidrun() {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 extendsThread {43
44 @Override45 public voidrun() {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) throwsInterruptedException {60 B.acquire(); C.acquire(); //开始只有A可以获取, BC都不可以获取, 保证了A最先执行
61 newThreadA().start();62 newThreadB().start();63 newThreadC().start();64 }65 }
注意:
lock是需要lock所有者去释放的, 即谁lock, 谁释放, 不可以跨线程, 会报java.lang.IllegalMonitorStateException;
semaphore是没有所有者的说法, 可以跨线程释放和获取.
这是一道java笔试题, 多线程的问题现在越来越多的出现在笔试中, 要好好学习.
水平有限, 如有错漏, 请指针, 欢迎拍砖, 共同探讨!
参考文献: