
这是一道蚂蚁金服二面的编程题
题目:交替打印零与奇偶数
给定一个数nums,然后交替打印出奇偶数。输出的长度为2nums,
你应该:至少用两种方法实现,并分析出优劣势。
举例:
输入:nums = 3
输出: “010203”
这道题与我之前分享的另外一道比较像 题目在这里 :阿里面试题分享(二)
但实际上比那道要简单些。因为没有要求写几个线程。
第一种解法:Lock+Condition
1package com.oho.alg;
2
3import java.util.concurrent.locks.Condition;
4import java.util.concurrent.locks.Lock;
5import java.util.concurrent.locks.ReentrantLock;
6
7public class PrintNums {
8
9 public final Lock lock = new ReentrantLock();
10 public Condition c0 = lock.newCondition();
11 public Condition c1 = lock.newCondition();
12 public int flag = 0;
13
14 private void print0(int num) {
15
16 lock.lock();
17 try {
18
19 for (int i = 1; i <= num; i++) {
20 if (flag == 0) {
21 System.out.print(0);
22 flag = 1;
23 c1.signal();
24 c0.await();
25 }
26
27 }
28
29 } catch (InterruptedException e) {
30 e.printStackTrace();
31 } finally {
32 lock.unlock();
33 }
34
35 }
36
37 private void print(int num) {
38
39 lock.lock();
40 try {
41
42 for (int i = 1; i <= num; i++) {
43 if (flag == 1) {
44
45 System.out.print(i);
46 flag = 0;
47 c0.signal();
48
49 if (i < num) {
50 c1.await();
51 }
52
53 }
54
55 }
56
57 } catch (InterruptedException e) {
58 e.printStackTrace();
59 } finally {
60 lock.unlock();
61 }
62
63 }
64
65 public void printNumsWithNum(int num) {
66
67 long start = System.currentTimeMillis();
68
69 Thread t1 = new Thread(() -> print0(num));
70 Thread t2 = new Thread(() -> print(num));
71
72 t1.start();
73 t2.start();
74
75 try {
76 t1.join();
77 t2.join();
78 } catch (InterruptedException e) {
79 e.printStackTrace();
80 }
81 System.out.println();
82 System.out.println("===============================================");
83 System.out.println("运行时长: " + (System.currentTimeMillis() - start));
84
85 }
86
87 public static void main(String[] args) {
88
89 new PrintNums().printNumsWithNum(10);
90
91 }
92}
93
94```java
95
96第二种解法:Semaphore
97
98```cs
99package com.oho.alg;
100
101import java.util.concurrent.Semaphore;
102
103public class PrintNumsUseSemaphore {
104
105 public Semaphore s1 = new Semaphore(1);
106 public Semaphore s2 = new Semaphore(0);
107
108 private void print0(int num) {
109
110 try {
111
112 for (int i = 1; i <= num; i++) {
113 //获取信号量,s1 - 1
114 s1.acquire();
115 System.out.print(0);
116 //释放信号量,s2 + 1
117 s2.release();
118 }
119
120 } catch (InterruptedException e) {
121 e.printStackTrace();
122 }
123
124 }
125
126 private void print(int num) {
127
128 try {
129 for (int i = 1; i <= num; i++) {
130 //获取信号量,s2 - 1
131 s2.acquire();
132 System.out.print(i);
133 //释放信号量,s1 + 1
134 s1.release();
135 }
136
137 } catch (InterruptedException e) {
138 e.printStackTrace();
139 }
140
141 }
142
143 public void printNumsWithNum(int num) {
144
145 long start = System.currentTimeMillis();
146
147 Thread t1 = new Thread(() -> print0(num));
148 Thread t2 = new Thread(() -> print(num));
149
150 t1.start();
151 t2.start();
152
153 try {
154 t1.join();
155 t2.join();
156 } catch (InterruptedException e) {
157 e.printStackTrace();
158 }
159 System.out.println();
160 System.out.println("===============================================");
161 System.out.println("运行时长: " + (System.currentTimeMillis() - start));
162
163 }
164
165 public static void main(String[] args) {
166
167 new PrintNumsUseSemaphore().printNumsWithNum(10);
168
169 }
170}
优劣势的话,如果在比较小的数据量下看不出来,我用nums = 800000,进行了测试:
| Lock+Condition | 运行时长: 9588 毫秒 |
| Semaphore | 运行时长: 9013 毫秒 |
随着nums的增大,Lock+Condition的运行时长比Semaphore越短。看起来Lock+Condition的性能更好些。至于为什么,因为涉及到锁的原理,这里就不多了,需要大家去看看源码,翻翻资料了。

关注公众号 获取更多精彩内容
