这是一道蚂蚁金服二面的编程题
题目:交替打印零与奇偶数
给定一个数nums,然后交替打印出奇偶数。输出的长度为2nums,
你应该:至少用两种方法实现,并分析出优劣势。
举例:
输入:nums = 3
输出: "010203"
这道题与我之前分享的另外一道比较像 题目在这里 :阿里面试题分享(二)
但实际上比那道要简单些。因为没有要求写几个线程。
第一种解法:Lock+Condition
package com.oho.alg; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class PrintNums { public final Lock lock = new ReentrantLock(); public Condition c0 = lock.newCondition(); public Condition c1 = lock.newCondition(); public int flag = 0; private void print0(int num) { lock.lock(); try { for (int i = 1; i <= num; i++) { if (flag == 0) { System.out.print(0); flag = 1; c1.signal(); c0.await(); } } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } private void print(int num) { lock.lock(); try { for (int i = 1; i <= num; i++) { if (flag == 1) { System.out.print(i); flag = 0; c0.signal(); if (i < num) { c1.await(); } } } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void printNumsWithNum(int num) { long start = System.currentTimeMillis(); Thread t1 = new Thread(() -> print0(num)); Thread t2 = new Thread(() -> print(num)); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(); System.out.println("==============================================="); System.out.println("运行时长: " + (System.currentTimeMillis() - start)); } public static void main(String[] args) { new PrintNums().printNumsWithNum(10); } }
第二种解法:Semaphore
package com.oho.alg; import java.util.concurrent.Semaphore; public class PrintNumsUseSemaphore { public Semaphore s1 = new Semaphore(1); public Semaphore s2 = new Semaphore(0); private void print0(int num) { try { for (int i = 1; i <= num; i++) { //获取信号量,s1 - 1 s1.acquire(); System.out.print(0); //释放信号量,s2 + 1 s2.release(); } } catch (InterruptedException e) { e.printStackTrace(); } } private void print(int num) { try { for (int i = 1; i <= num; i++) { //获取信号量,s2 - 1 s2.acquire(); System.out.print(i); //释放信号量,s1 + 1 s1.release(); } } catch (InterruptedException e) { e.printStackTrace(); } } public void printNumsWithNum(int num) { long start = System.currentTimeMillis(); Thread t1 = new Thread(() -> print0(num)); Thread t2 = new Thread(() -> print(num)); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(); System.out.println("==============================================="); System.out.println("运行时长: " + (System.currentTimeMillis() - start)); } public static void main(String[] args) { new PrintNumsUseSemaphore().printNumsWithNum(10); } }
优劣势的话,如果在比较小的数据量下看不出来,我用nums = 800000,进行了测试:
Lock+Condition |
运行时长: 9588 毫秒 |
Semaphore | 运行时长: 9013 毫秒 |
随着nums的增大,Lock+Condition的运行时长比Semaphore越短。看起来Lock+Condition的性能更好些。至于为什么,因为涉及到锁的原理,这里就不多了,需要大家去看看源码,翻翻资料了。