赞
踩
2年半第一次出去面试,也是第一次面试阿里,打击不小,收货也不少,最终倒在二面笔试题上,虽有不甘,但仍需收拾心情,继续努力。
在一面上,跟网上大多数的反馈相同,都是比较Java基础项,然后往深度问。我整理了下:
因为我简历上写了关于修改Apollo(携程的配置中心)源码,应用到我们系统中,所以问了我怎么实现,还问到了配置是推还是拉,我果断回答了拉,然后大致就结束了,其中细节不多数。
后面就开始问了关于Java基础知识点了,先是问了HashMap线程安全,后面问了其中的hash值是如何确定的,为何每次扩展只能2的倍数。回答完这个之后,问有没有线程安全的HashMap,自然过渡到ConcurrentHashMap,问是如何实现线程安全的。然后回答了分段锁,之后又问了关于JDK1.8前后的实现,为什么要改为使用synchronized,回答了synchronized是jvm层实现的,后期jvm优化,会跟随着一起优化。
关于Map的问完,开始问ThreadLocal相关知识点了,是如何实现线程变量的,然后巴拉巴拉说了代码实现,还有关于ThreadLocalMap的数据结果是跟Jdk1.8之前的HashMap相似。
最后基础问完了,因为回答的都算比较流畅,所以时间过得也比较少,这里问了我关于秒杀系统怎么设计,我就回答了使用redis和MQ来进行削峰,使用redis存储库存,使用MQ进行异步业务处理。后面追问了关于redis集群如果挂了怎么办。我当时没有想到很好的方法,只想到了多级缓存,但是感觉答案不对。然后我提问了怎么解决,方案是加机器和多级缓存,就算数据错误,也要保住服务可用。
到这大致一面就结束了。
这里发生了点事,因为我是住在拱墅这,然后面试部门是在滨江,我当时问了下能否换职场位置,然后他说不能,我也没太在意,想着自己换地方。之后等了5天,没有收到反应,然后有人提醒下我去找了Boss上的推荐人,问了下,他说一面是通过了,但是备注上写着居住太远,意愿不强吧,差点没给我二面的机会了。问了之后再跟他反应这个没事,然后就顺利约到11号二面了,因为10号阿里20周年年会。
这面说实话有点可惜了。首先我这面是笔试题,之前一直在猜测会考哪方面的,网上也找了点资料,最后还是觉得会考多线程这块。当时想着应该会有代码自动补全功能把,因为我平时打代码大多数还是依靠这个功能的,有些api方法和关键字名可能拼不全。然后首先第一个给我的打击就是全程txt文件上直接手打,不能使用代码补全。之后再来说下关于面试题目把:
有三个线程,线程一只打印t1,线程二只打印t2,线程三只打印t3,输出到三个文件,第一个文件的打印顺序是t1 t2 t3 。。。第二个是t2 t3 t1 。。。 第三个是t3 t1 t2
看到这个题目,有点虚,主要文件操作这块的api记不全,如果可以找资料倒是可以。然后面试官了解了之后给我改了下题目:
有三个线程,线程一只打印t1,线程二只打印t2,线程三只打印t3,在控制台上输出t1 t2 t3 。。循环5遍 之后输出t2 t3 t1。。5遍 再输出t3 t1 t2。。5遍之后就循环
先来看第一题:
有三个线程,线程一只打印t1,线程二只打印t2,线程三只打印t3,输出到三个文件,第一个文件的打印顺序是t1 t2 t3 。。。第二个是t2 t3 t1 。。。 第三个是t3 t1 t2
哎,这题比较简单,当时主要还是文件流的类不熟,自己手写不会拼写,下面给出之后我自己写的两个答案:
第一个是使用notify实现:
/** * 有三个线程,线程一只打印t1,线程二只打印t2,线程三只打印t3,输出到三个文件, * 第一个文件的打印顺序是t1 t2 t3 。。。第二个是t2 t3 t1 。。。 第三个是t3 t1 t2 * * 使用notify实现 */ public class DemoTest { /** * 次数标识,用来区分那个线程打印 */ private static volatile int count = 0; private static Object lock = new Object(); private static File fileA = new File("/Users/shileizhou/test/fileA.txt"); private static File fileB = new File("/Users/shileizhou/test/fileB.txt"); private static File fileC = new File("/Users/shileizhou/test/fileC.txt"); public static void main(String[] args) { try { fileA.createNewFile(); fileB.createNewFile(); fileC.createNewFile(); BufferedWriter bufferedWriterA = new BufferedWriter(new FileWriter(fileA,true)); BufferedWriter bufferedWriterB = new BufferedWriter(new FileWriter(fileB,true)); BufferedWriter bufferedWriterC = new BufferedWriter(new FileWriter(fileC,true)); PrintT1Thread printT1Thread = new PrintT1Thread(); printT1Thread.bufferedWriterA = bufferedWriterA; printT1Thread.bufferedWriterB = bufferedWriterB; printT1Thread.bufferedWriterC = bufferedWriterC; PrintT2Thread printT2Thread = new PrintT2Thread(); printT2Thread.bufferedWriterA = bufferedWriterA; printT2Thread.bufferedWriterB = bufferedWriterB; printT2Thread.bufferedWriterC = bufferedWriterC; PrintT3Thread printT3Thread = new PrintT3Thread(); printT3Thread.bufferedWriterA = bufferedWriterA; printT3Thread.bufferedWriterB = bufferedWriterB; printT3Thread.bufferedWriterC = bufferedWriterC; new Thread(printT1Thread).start(); new Thread(printT2Thread).start(); new Thread(printT3Thread).start(); } catch (IOException e) { e.printStackTrace(); } } static class PrintT1Thread implements Runnable { BufferedWriter bufferedWriterA ; BufferedWriter bufferedWriterB ; BufferedWriter bufferedWriterC ; @Override public void run() { while (true){ synchronized (lock) { try { if (count % 3 == 0) { bufferedWriterA.write("t1"); bufferedWriterA.flush(); if (count != 0) { bufferedWriterB.write("t1"); bufferedWriterC.write("t1"); bufferedWriterB.flush(); bufferedWriterC.flush(); } count++; lock.notifyAll(); } else { lock.wait(); } } catch (Exception e) { e.printStackTrace(); } } } } } static class PrintT2Thread implements Runnable { BufferedWriter bufferedWriterA ; BufferedWriter bufferedWriterB ; BufferedWriter bufferedWriterC ; @Override public void run() { while (true){ synchronized (lock) { try { if (count % 3 == 1) { bufferedWriterA.write("t2"); bufferedWriterB.write("t2"); bufferedWriterA.flush(); bufferedWriterB.flush(); if (count > 1) { bufferedWriterC.write("t2"); bufferedWriterC.flush(); } count++; lock.notifyAll(); } else { lock.wait(); } } catch (Exception e) { e.printStackTrace(); } } } } } static class PrintT3Thread implements Runnable { BufferedWriter bufferedWriterA ; BufferedWriter bufferedWriterB ; BufferedWriter bufferedWriterC ; @Override public void run() { while (true){ synchronized (lock) { try { if (count % 3 == 2) { bufferedWriterA.write("t3"); bufferedWriterB.write("t3"); bufferedWriterC.write("t3"); bufferedWriterA.flush(); bufferedWriterB.flush(); bufferedWriterC.flush(); count++; lock.notifyAll(); } else { lock.wait(); } } catch (Exception e) { e.printStackTrace(); } } } } } }
第二种是使用condition方式实现:
/** * 有三个线程,线程一只打印t1,线程二只打印t2,线程三只打印t3,输出到三个文件, * 第一个文件的打印顺序是t1 t2 t3 。。。第二个是t2 t3 t1 。。。 第三个是t3 t1 t2 * * 使用Condition */ public class DemoTest2 { /** * 次数标识,用来区分那个线程打印 */ private static volatile int count = 0; private static Lock lock = new ReentrantLock(); private static Condition t1Condition = lock.newCondition(); private static Condition t2Condition = lock.newCondition(); private static Condition t3Condition = lock.newCondition(); private static File fileA = new File("/Users/shileizhou/test/fileA.txt"); private static File fileB = new File("/Users/shileizhou/test/fileB.txt"); private static File fileC = new File("/Users/shileizhou/test/fileC.txt"); public static void main(String[] args) { try { fileA.createNewFile(); fileB.createNewFile(); fileC.createNewFile(); BufferedWriter bufferedWriterA = new BufferedWriter(new FileWriter(fileA,true)); BufferedWriter bufferedWriterB = new BufferedWriter(new FileWriter(fileB,true)); BufferedWriter bufferedWriterC = new BufferedWriter(new FileWriter(fileC,true)); DemoTest.PrintT1Thread printT1Thread = new DemoTest.PrintT1Thread(); printT1Thread.bufferedWriterA = bufferedWriterA; printT1Thread.bufferedWriterB = bufferedWriterB; printT1Thread.bufferedWriterC = bufferedWriterC; DemoTest.PrintT2Thread printT2Thread = new DemoTest.PrintT2Thread(); printT2Thread.bufferedWriterA = bufferedWriterA; printT2Thread.bufferedWriterB = bufferedWriterB; printT2Thread.bufferedWriterC = bufferedWriterC; DemoTest.PrintT3Thread printT3Thread = new DemoTest.PrintT3Thread(); printT3Thread.bufferedWriterA = bufferedWriterA; printT3Thread.bufferedWriterB = bufferedWriterB; printT3Thread.bufferedWriterC = bufferedWriterC; new Thread(printT1Thread).start(); new Thread(printT2Thread).start(); new Thread(printT3Thread).start(); } catch (IOException e) { e.printStackTrace(); } } static class PrintT1Thread implements Runnable { BufferedWriter bufferedWriterA ; BufferedWriter bufferedWriterB ; BufferedWriter bufferedWriterC ; @Override public void run() { while (true){ lock.lock(); try { if (count % 3 == 0) { bufferedWriterA.write("t1"); bufferedWriterA.flush(); if (count != 0) { bufferedWriterB.write("t1"); bufferedWriterC.write("t1"); bufferedWriterB.flush(); bufferedWriterC.flush(); } count++; Thread.sleep(500); t2Condition.signal(); } else { t1Condition.await(); } } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } } } static class PrintT2Thread implements Runnable { BufferedWriter bufferedWriterA ; BufferedWriter bufferedWriterB ; BufferedWriter bufferedWriterC ; @Override public void run() { while (true){ lock.lock(); try { if (count % 3 == 1) { bufferedWriterA.write("t2"); bufferedWriterB.write("t2"); bufferedWriterA.flush(); bufferedWriterB.flush(); if (count > 1) { bufferedWriterC.write("t2"); bufferedWriterC.flush(); } Thread.sleep(500); count++; t3Condition.signal(); } else { t2Condition.await(); } } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } } } static class PrintT3Thread implements Runnable { BufferedWriter bufferedWriterA ; BufferedWriter bufferedWriterB ; BufferedWriter bufferedWriterC ; @Override public void run() { while (true){ lock.lock(); try { if (count % 3 == 2) { bufferedWriterA.write("t3"); bufferedWriterB.write("t3"); bufferedWriterC.write("t3"); bufferedWriterA.flush(); bufferedWriterB.flush(); bufferedWriterC.flush(); Thread.sleep(500); count++; t1Condition.signal(); } else { t3Condition.await(); } } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } } } }
这题败在了对于IO文件流的类不熟悉。
下面开始第二题:
有三个线程,线程一只打印t1,线程二只打印t2,线程三只打印t3,在控制台上输出t1 t2 t3 。。循环5遍
之后输出t2 t3 t1。。5遍 再输出t3 t1 t2。。5遍之后就循环
这是我考完之后想到的:
/** * 有三个线程,线程一只打印t1,线程二只打印t2,线程三只打印t3,在控制台上输出t1 t2 t3 。。循环5遍 * 之后输出t2 t3 t1。。5遍 再输出t3 t1 t2。。5遍之后就循环 */ public class DemoTest4 { private static volatile int count = 0; private static volatile int signA = 0; private static volatile int signB = 1; private static volatile int signC = 2; private static Object lock = new Object(); public static void main(String[] args) { new Thread(new PrintT1Thread()).start(); new Thread(new PrintT2Thread()).start(); new Thread(new PrintT3Thread()).start(); } static class PrintT1Thread implements Runnable{ @Override public void run() { while (true){ synchronized (lock){ try{ if (count % 3 == signA){ System.out.print("t1 "); count++; if (count % 15 == 0){ signA = (signA + 2) % 3; signB = (signB + 2) % 3; signC = (signC + 2) % 3; } lock.notifyAll(); }else { lock.wait(); } }catch (Exception e){ } } } } } static class PrintT2Thread implements Runnable{ @Override public void run() { while (true){ synchronized (lock){ try{ if (count % 3 == signB){ System.out.print("t2 "); count++; if (count % 15 == 0){ signA = (signA + 2) % 3; signB = (signB + 2) % 3; signC = (signC + 2) % 3; } lock.notifyAll(); }else { lock.wait(); } }catch (Exception e){ } } } } } static class PrintT3Thread implements Runnable{ @Override public void run() { while(true){ synchronized (lock){ try{ if (count % 3 == signC){ System.out.print("t3 "); count++; if (count % 15 == 0){ signA = (signA + 2) % 3; signB = (signB + 2) % 3; signC = (signC + 2) % 3; } lock.notifyAll(); }else { lock.wait(); } }catch (Exception e){ } } } } } }
还有别人提供了一种其他思路:
/** * 有三个线程,线程一只打印t1,线程二只打印t2,线程三只打印t3,在控制台上输出t1 t2 t3 。。循环5遍 * 之后输出t2 t3 t1。。5遍 再输出t3 t1 t2。。5遍之后就循环 */ public class DemoTest3 { public static void main(String[] args) { for (int i = 1; i <=4 ; i++) { for (int j = 0; j < 5; j++) { NumberThread n = new NumberThread(); n.state = i; Thread t1 = new Thread(n); t1.setName("t1"); Thread t2 = new Thread(n); t2.setName("t2"); Thread t3 = new Thread(n); t3.setName("t3"); t1.start(); t2.start(); t3.start(); try{ Thread.sleep(500); System.out.println(); }catch (Exception e){ } } if (i == 3){ i = 0; } } } static class NumberThread implements Runnable{ private int state; private int count = 0; @Override public void run() { while (true){ synchronized (this){ if (count == 3){ break; } String name = Thread.currentThread().getName(); if (name.contains(state + "")){ System.out.print(name); count++; state++; }else { try{ wait(); }catch (Exception e){ } } if (state == 4){ state = 1; } notifyAll(); if (count == 3){ break; } } } } } }
感觉还是败在了平时太过于依赖IDEA自动补全了,使用txt编程刚开始心态就有点问题了。继续努力,再战阿里~~~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。