2019下半年阿里面试失败总结


结果预览

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编程刚开始心态就有点问题了。继续努力,再战阿里~~~

你可能感兴趣的:(个人面试总结)