关于面试:面试网络

网络 79. http 响应码 301 和 302 代表的是什么?有什么区别? 答:301,302 都是HTTP状态的编码,都代表着某个URL产生了转移。 区别: 301 redirect: 301 代表永久性转移(Permanently Moved)。302 redirect: 302 代表暂时性转移(Temporarily Moved )。 80. forward 和 redirect 的区别? Forward和Redirect代表了两种申请转发形式:间接转发和间接转发。 间接转发形式(Forward),客户端和浏览器只收回一次申请,Servlet、HTML、JSP或其它信息资源,由第二个信息资源响应该申请,在申请对象request中,保留的对象对于每个信息资源是共享的。 间接转发形式(Redirect)理论是两次HTTP申请,服务器端在响应第一次申请的时候,让浏览器再向另外一个URL发出请求,从而达到转发的目标。 举个艰深的例子: 间接转发就相当于:“A找B借钱,B说没有,B去找C借,借到借不到都会把消息传递给A”; 间接转发就相当于:"A找B借钱,B说没有,让A去找C借"。 81. 简述 tcp 和 udp的区别? TCP面向连贯(如打电话要先拨号建设连贯);UDP是无连贯的,即发送数据之前不须要建设连贯。TCP提供牢靠的服务。也就是说,通过TCP连贯传送的数据,无差错,不失落,不反复,且按序达到;UDP尽最大致力交付,即不保障牢靠交付。Tcp通过校验和,重传管制,序号标识,滑动窗口、确认应答实现牢靠传输。如丢包时的重发管制,还能够对秩序乱掉的分包进行顺序控制。UDP具备较好的实时性,工作效率比TCP高,实用于对高速传输和实时性有较高的通信或播送通信。每一条TCP连贯只能是点到点的;UDP反对一对一,一对多,多对一和多对多的交互通信。TCP对系统资源要求较多,UDP对系统资源要求较少。82. tcp 为什么要三次握手,两次不行吗?为什么? 为了实现牢靠数据传输, TCP 协定的通信单方, 都必须保护一个序列号, 以标识发送进来的数据包中, 哪些是曾经被对方收到的。 三次握手的过程即是通信单方互相告知序列号起始值, 并确认对方曾经收到了序列号起始值的必经步骤。 如果只是两次握手, 至少只有连贯发起方的起始序列号能被确认, 另一方抉择的序列号则得不到确认。 83. 说一下 tcp 粘包是怎么产生的? ①. 发送方产生粘包 采纳TCP协定传输数据的客户端与服务器常常是放弃一个长连贯的状态(一次连贯发一次数据不存在粘包),单方在连接不断开的状况下,能够始终传输数据;但当发送的数据包过于的小时,那么TCP协定默认的会启用Nagle算法,将这些较小的数据包进行合并发送(缓冲区数据发送是一个堆压的过程);这个合并过程就是在发送缓冲区中进行的,也就是说数据发送进去它曾经是粘包的状态了。 ②. 接管方产生粘包 接管方采纳TCP协定接收数据时的过程是这样的:数据到底接管方,从网络模型的下方传递至传输层,传输层的TCP协定解决是将其搁置接收缓冲区,而后由应用层来被动获取(C语言用recv、read等函数);这时会呈现一个问题,就是咱们在程序中调用的读取数据函数不能及时的把缓冲区中的数据拿进去,而下一个数据又到来并有一部分放入的缓冲区开端,等咱们读取数据时就是一个粘包。(放数据的速度 > 应用层拿数据速度)  84. OSI 的七层模型都有哪些? 应用层:网络服务与最终用户的一个接口。表示层:数据的示意、平安、压缩。会话层:建设、治理、终止会话。传输层:定义传输数据的协定端口号,以及流控和过错校验。网络层:进行逻辑地址寻址,实现不同网络之间的门路抉择。数据链路层:建设逻辑连贯、进行硬件地址寻址、过错校验等性能。物理层:建设、保护、断开物理连贯。85. get 和 post 申请有哪些区别? GET在浏览器回退时是有害的,而POST会再次提交申请。GET产生的URL地址能够被Bookmark,而POST不能够。GET申请会被浏览器被动cache,而POST不会,除非手动设置。GET申请只能进行url编码,而POST反对多种编码方式。GET申请参数会被残缺保留在浏览器历史记录里,而POST中的参数不会被保留。GET申请在URL中传送的参数是有长度限度的,而POST么有。对参数的数据类型,GET只承受ASCII字符,而POST没有限度。GET比POST更不平安,因为参数间接裸露在URL上,所以不能用来传递敏感信息。GET参数通过URL传递,POST放在Request body中。86. 如何实现跨域? 形式一:图片ping或script标签跨域图片ping罕用于跟踪用户点击页面或动静广告曝光次数。 script标签能够失去从其余起源数据,这也是JSONP依赖的依据。  ...

November 16, 2020 · 2 min · jiezi

关于面试:面试异常

74. throw 和 throws 的区别?75. final、finally、finalize 有什么区别?76. try-catch-finally 中哪个局部能够省略?77. try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?78. 常见的异样类有哪些?异样 74. throw 和 throws 的区别? throw: 示意办法内抛出某种异样对象如果异样对象是非 RuntimeException 则须要在办法申明时加上该异样的抛出 即须要加上 throws 语句 或者 在办法体内 try catch 解决该异样,否则编译报错执行到 throw 语句则前面的语句块不再执行 throws: 办法的定义上应用 throws 示意这个办法可能抛出某种异样须要由办法的调用者进行异样解决75. final、finally、finalize 有什么区别? final能够润饰类、变量、办法,润饰类示意该类不能被继承、润饰办法示意该办法不能被重写、润饰变量示意该变量是一个常量不能被从新赋值。finally个别作用在try-catch代码块中,在解决异样的时候,通常咱们将肯定要执行的代码办法finally代码块中,示意不论是否出现异常,该代码块都会执行,个别用来寄存一些敞开资源的代码。finalize是一个办法,属于Object类的一个办法,而Object类是所有类的父类,该办法个别由垃圾回收器来调用,当咱们调用System的gc()办法的时候,由垃圾回收器调用finalize(),回收垃圾。 76. try-catch-finally 中哪个局部能够省略? 答:catch 能够省略 起因: 更为严格的说法其实是:try只适宜解决运行时异样,try+catch适宜解决运行时异样+一般异样。也就是说,如果你只用try去解决一般异样却不加以catch解决,编译是通不过的,因为编译器硬性规定,一般异样如果抉择捕捉,则必须用catch显示申明以便进一步解决。而运行时异样在编译时没有如此规定,所以catch能够省略,你加上catch编译器也感觉无可非议。 实践上,编译器看任何代码都不悦目,都感觉可能有潜在的问题,所以你即便对所有代码加上try,代码在运行期时也只不过是在失常运行的根底上加一层皮。然而你一旦对一段代码加上try,就等于显示地承诺编译器,对这段代码可能抛出的异样进行捕捉而非向上抛出解决。如果是一般异样,编译器要求必须用catch捕捉以便进一步解决;如果运行时异样,捕捉而后抛弃并且+finally开头解决,或者加上catch捕捉以便进一步解决。 至于加上finally,则是在不论有没捕捉异样,都要进行的“开头”解决。 77. try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗? 答:会执行,在 return 前执行。 代码示例1: /* * 如果catch外面有return语句,finally外面的代码还会执行吗? */public class FinallyDemo2 { public static void main(String[] args) { System.out.println(getInt()); } public static int getInt() { int a = 10; try { System.out.println(a / 0); a = 20; } catch (ArithmeticException e) { a = 30; return a; } finally { a = 40; } }}执行后果:30 ...

November 16, 2020 · 1 min · jiezi

关于面试:面试Java-Web

Java Web jsp简介:HTML善于显示页面,然而它并不能调用Java代码动静的生成内容;Servlet善于调用Java程序,生成动静内容,然而Servlet不善于显示页面。 jsp(Java Server Pages)联合了HTML和Servlet的长处,实质上是运行在服务端的一个Servlet,Tomcat等Servlet容器会将jsp文件中的内容通过out.write()、out.print()等办法间接输入给浏览器,浏览器获取到的仍然是一个html文档,而后再进行渲染等 JSP根本语法 1、模板元素 模板元素指就是JSP中的HTML代码,模板元素的内容会作为out.write()的参数,间接输入到页面中,在HTML中怎么写,在JSP中就怎么写 2、 脚本片段 脚本片段写在 <% %>中,能够在脚本片段中间接编写Java代码,脚本片段会一成不变的复制到java文件的service办法中的对应地位 3、表达式 JSP的表达式写在<%= %>中,JSP表达式能够将一个对象间接输入到页面中,JSP表达式中的内容最终会作为out.print()办法的参数,输入到页面中 4、正文 JSP的正文写在 <%-- --%>中 5、申明 JSP中的申明写在<%! %>中 6、JSP指令 JSP指令的格局:<%@ 指令名 属性名1=”属性值1” 属性名2=”属性值2” %>,举例: a、page指令:b、include指令c、taglib指令 7、JSP动作标签格局:<jsp:标签名 属性名=“属性值”></jsp:标签名>a、申请转发 <jsp:forward page=""></jsp:forward>b、动静蕴含 <jsp:include page="/include2/2.jsp"></jsp:include>64. jsp 和 servlet 有什么区别? jsp经编译后就变成了Servlet.(JSP的实质就是Servlet,JVM只能辨认java的类,不能辨认JSP的代码,Web容器将JSP的代码编译成JVM可能辨认的java类)jsp更善于体现于页面显示,servlet更擅长于逻辑管制。Servlet中没有内置对象,Jsp中的内置对象都是必须通过HttpServletRequest对象,HttpServletResponse对象以及HttpServlet对象失去。Jsp是Servlet的一种简化,应用Jsp只须要实现程序员须要输入到客户端的内容,Jsp中的Java脚本如何镶嵌到一个类中,由Jsp容器实现。而Servlet则是个残缺的Java类,这个类的Service办法用于生成对客户端的响应。65. jsp 的9个内置对象别离是什么?作用是什么? JSP有9个内置对象: request:封装客户端的申请,其中蕴含来自GET或POST申请的参数;response:封装服务器对客户端的响应;pageContext:通过该对象能够获取其余对象;session:封装用户会话的对象;application:封装服务器运行环境的对象;out:输入服务器响应的输入流对象;config:Web利用的配置对象;page:JSP页面自身(相当于Java程序中的this);exception:封装页面抛出异样的对象。66. 说一下 jsp 的 4 种作用域? JSP中的四种作用域包含page、request、session和application,具体来说: pageContext对象,最小的域对象,能够在以后页面中共享数据,一旦切换页面,则域中的属性就会失落,该对象次要用来向标签中传递数据。request对象,能够在一次申请中共享数据,一旦发送屡次申请,则域中的属性就会失落。次要用于在转发时共享数据(request域中属性在转发时无效,重定向时有效)。session对象,能够在一次会话中共享数据,一旦会话完结则域中的属性失落。会话:就是一次关上敞开浏览器的过程。application对象,是最大的域对象,作用范畴是整个我的项目,只有不敞开服务器则application域中的属性始终无效。67. session 和 cookie 有什么区别? 1、存储地位不同 cookie的数据信息寄存在客户端浏览器上。session的数据信息寄存在服务器上。 2、存储容量不同 单个cookie保留的数据<=4KB,一个站点最多保留20个Cookie。对于session来说并没有下限,但出于对服务器端的性能思考,session内不要寄存过多的货色,并且设置session删除机制。 3、存储形式不同 cookie中只能保存ASCII字符串,并须要通过编码方式存储为Unicode字符或者二进制数据。session中可能存储任何类型的数据,包含且不限于string,integer,list,map等。 4、隐衷策略不同 cookie对客户端是可见的,所以它是不平安的。session存储在服务器上,不存在敏感信息透露的危险。 5、有效期上不同 能够通过设置cookie的属性,达到使cookie长期有效的成果。session依赖于名为JSESSIONID的cookie,而cookie JSESSIONID的过期工夫默认为-1,只需敞开窗口该session就会生效,因此session不能达到长期有效的成果。session的过期工夫是从session不流动的时候开始计算(如果session始终流动,session就总不会过期,从该Session未被拜访,开始计时; 一旦Session被拜访,计时清0); ...

November 16, 2020 · 2 min · jiezi

关于面试:面试反射

反射 57. 什么是反射? 反射次要是指程序能够拜访、检测和批改它自身状态或行为的一种能力 Java反射:在Java运行时环境中,对于任意一个类,是否晓得这个类有哪些属性和办法?对于任意一个对象,是否调用它的任意一个办法 Java反射机制次要提供了以下性能: 在运行时判断任意一个对象所属的类。在运行时结构任意一个类的对象。在运行时判断任意一个类所具备的成员变量和办法。在运行时调用任意一个对象的办法。 58. 什么是 java 序列化?什么状况下须要序列化? 简略说就是为了保留在内存中的各种对象的状态(也就是实例变量,不是办法),并且能够把保留的对象状态再读出来。尽管你能够用你本人的各种各样的办法来保留object states,然而Java给你提供一种应该比你本人好的保留对象状态的机制,那就是序列化。什么状况下须要序列化: a)当你想把的内存中的对象状态保留到一个文件中或者数据库中时候;b)当你想用套接字在网络上传送对象的时候;c)当你想通过RMI传输对象的时候; 59. 动静代理是什么?有哪些利用? 动静代理: 当想要给实现了某个接口的类中的办法,加一些额定的解决。比如说加日志,加事务等。能够给这个类创立一个代理,故名思议就是创立一个新的类,这个类不仅蕴含原来类办法的性能,而且还在原来的根底上增加了额定解决的新类。这个代理类并不是定义好的,是动静生成的。具备解耦意义,灵便,扩展性强。 动静代理的利用: Spring的AOP加事务加权限加日志60. 怎么实现动静代理? 首先必须定义一个接口,还要有一个InvocationHandler(将实现接口的类的对象传递给它)解决类。再有一个工具类Proxy(习惯性将其称为代理类,因为调用他的newInstance()能够产生代理对象,其实他只是一个产生代理对象的工具类)。利用到InvocationHandler,拼接代理类源码,将其编译生成代理类的二进制码,利用加载器加载,并将其实例化产生代理对象,最初返回。 第五模块答案对象拷贝 61. 为什么要应用克隆? 想对一个对象进行解决,又想保留原有的数据进行接下来的操作,就须要克隆了,Java语言中克隆针对的是类的实例。 62. 如何实现对象克隆? 有两种形式: 1). 实现Cloneable接口并重写Object类中的clone()办法; 2). 实现Serializable接口,通过对象的序列化和反序列化实现克隆,能够实现真正的深度克隆,代码如下: import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;public class MyUtil { private MyUtil() { throw new AssertionError(); } @SuppressWarnings("unchecked") public static <T extends Serializable> T clone(T obj) throws Exception { ByteArrayOutputStream bout = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bout); oos.writeObject(obj); ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bin); return (T) ois.readObject(); // 阐明:调用ByteArrayInputStream或ByteArrayOutputStream对象的close办法没有任何意义 // 这两个基于内存的流只有垃圾回收器清理对象就可能开释资源,这一点不同于对外部资源(如文件流)的开释 }}上面是测试代码: ...

November 16, 2020 · 2 min · jiezi

关于面试:面试多线程

多线程35. 并行和并发有什么区别? 并行是指多个事件在同一时刻产生;而并发是指多个事件在同一时间距离产生。并发:指利用可能交替执行不同的工作,其实并发有点相似于多线程的原理,多线程并非是同时执行多个工作而是疾速切换着执行。并行:指利用可能同时执行不同的工作,例如,边吃饭边听音乐并发是指一个处理器同时解决多个工作。并行是指多个处理器或者是多核的处理器同时解决多个不同的工作。并发是逻辑上的同时产生,而并行是物理上的同时产生。如hadoop分布式集群。所以并发编程的指标是充沛的利用处理器的每一个核,以达到最高的解决性能。 36. 过程和线程的区别? 简而言之,过程是程序运行和资源分配的根本单位,一个程序至多有一个过程,一个过程至多有一个或多个线程。过程在执行过程中领有独立的内存单元,而多个线程共享内存资源,缩小切换次数,从而效率更高。**线程是过程的一个实体同一过程中的多个线程之间能够并发执行,是cpu调度和分派的根本单位,是比程序更小的能独立运行的根本单位。线程是过程的一个实体同一过程中的多个线程之间能够并发执行**。 37. 守护线程是什么? 守护线程(即daemon thread),是个服务线程,精确地来说就是服务其余的线程,这是它的作用——而其余的线程只有一种,那就是用户线程。所以java里线程分2种,1、守护线程,比方垃圾回收线程,就是最典型的守护线程。2、用户线程,就是应用程序里的自定义线程。当所有非守护线程完结时,没有了被守护者,守护线程也就没有工作可做了,也就没有持续运行程序的必要了,程序也就终止了,同时会“杀死”所有守护线程。 也就是说,只有有任何非守护线程还在运行,程序就不会终止。 38. 创立线程有哪几种形式? ①. 继承Thread类创立线程类 继承Thread类,并重写该类的run办法,该run办法的办法体就代表了线程要实现的工作。因而把run()办法称为执行体。创立Thread子类的实例,即创立了线程对象。调用线程对象的start()办法来启动该线程。public class FirstThreadTest extends Thread { int i = 0; //重写run办法,run办法的办法体就是线程执行体 public void run() { for (; i < 100; i++) { System.out.println(getName() + " " + i); } } public static void main(String[] args) { for (int i = 0; i < 100; i++) { //Thread.currentThread()办法返回以后正在执行的线程对象。 //GetName()办法返回调用该办法的线程的名字。 System.out.println(Thread.currentThread().getName() + " : " + i); if (i == 50) { //创立Thread子类的实例,即创立了线程对象 new FirstThreadTest().start(); new FirstThreadTest().start(); } } }②. 通过Runnable接口创立线程类 ...

November 14, 2020 · 2 min · jiezi

关于面试:面试容器

18. java 容器都有哪些? 罕用容器的图录: 19. Collection 和 Collections 有什么区别? java.util.Collection 是一个汇合接口(汇合类的一个顶级接口)。它提供了对汇合对象进行基本操作的通用接口办法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的汇合提供了最大化的对立操作形式,其间接继承接口有List与Set。Collections则是汇合类的一个工具类/帮忙类,其中提供了一系列静态方法,用于对汇合中元素进行排序、搜寻以及线程平安等各种操作。20. List、Set、Map 之间的区别是什么? 21. HashMap 和 Hashtable 有什么区别? hashMap去掉了HashTable 的contains办法,然而加上了containsValue()和containsKey()办法。hashTable同步的,而HashMap是非同步的,效率上逼hashTable要高。hashMap容许空键值,而hashTable不容许。22. 如何决定应用 HashMap 还是 TreeMap? 对于在Map中插入、删除和定位元素这类操作,HashMap是最好的抉择。然而,如果你须要对一个有序的key汇合进行遍历,TreeMap是更好的抉择。基于你的collection的大小,兴许向HashMap中增加元素会更快,将map换为TreeMap进行有序key的遍历。 23. 说一下 HashMap 的实现原理? HashMap概述: HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并容许应用null值和null键。此类不保障映射的程序,特地是它不保障该程序恒久不变。  HashMap的数据结构: 在java编程语言中,最根本的构造就是两种,一个是数组,另外一个是模仿指针(援用),所有的数据结构都能够用这两个根本构造来结构的,HashMap也不例外。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。 当咱们往Hashmap中put元素时,首先依据key的hashcode从新计算hash值,杜绝hash值得到这个元素在数组中的地位(下标),如果该数组在该地位上曾经寄存了其余元素,那么在这个地位上的元素将以链表的模式寄存,新退出的放在链头,最先退出的放入链尾.如果数组中该地位没有元素,就间接将该元素放到数组的该地位上。 须要留神Jdk 1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来进步查问效率,从原来的O(n)到O(logn) 24. 说一下 HashSet 的实现原理? HashSet底层由HashMap实现HashSet的值寄存于HashMap的key上HashMap的value对立为PRESENT25. ArrayList 和 LinkedList 的区别是什么? 最显著的区别是 ArrrayList底层的数据结构是数组,反对随机拜访,而 LinkedList 的底层数据结构是双向循环链表,不反对随机拜访。应用下标拜访一个元素,ArrayList 的工夫复杂度是 O(1),而 LinkedList 是 O(n)。 26. 如何实现数组和 List 之间的转换? List转换成为数组:调用ArrayList的toArray办法。数组转换成为List:调用Arrays的asList办法。27. ArrayList 和 Vector 的区别是什么? Vector是同步的,而ArrayList不是。然而,如果你寻求在迭代的时候对列表进行扭转,你应该应用CopyOnWriteArrayList。 ArrayList比Vector快,它因为有同步,不会过载。 ArrayList更加通用,因为咱们能够应用Collections工具类轻易地获取同步列表和只读列表。28. Array 和 ArrayList 有何区别? ...

November 14, 2020 · 1 min · jiezi

关于面试:面试1

1. JDK 和 JRE 有什么区别? JDK:Java Development Kit 的简称,java 开发工具包,提供了 java 的开发环境和运行环境。JRE:Java Runtime Environment 的简称,java 运行环境,为 java 的运行提供了所需环境。具体来说 JDK 其实蕴含了 JRE,同时还蕴含了编译 java 源码的编译器 javac,还蕴含了很多 java 程序调试和剖析的工具。简略来说:如果你须要运行 java 程序,只需装置 JRE 就能够了,如果你须要编写 java 程序,须要装置 JDK。 2. == 和 equals 的区别是什么? == 解读 对于根本类型和援用类型 == 的作用成果是不同的,如下所示: 根本类型:比拟的是值是否雷同;援用类型:比拟的是援用是否雷同;代码示例: String x = "string";String y = "string";String z = new String("string");System.out.println(x==y); // trueSystem.out.println(x==z); // falseSystem.out.println(x.equals(y)); // trueSystem.out.println(x.equals(z)); // true代码解读:因为 x 和 y 指向的是同一个援用,所以 == 也是 true,而 new String()办法则重写开拓了内存空间,所以 == 后果为 false,而 equals 比拟的始终是值,所以后果都为 true。 ...

November 14, 2020 · 3 min · jiezi

关于面试:前端面试每日-31-第576天

明天的知识点 (2020.11.12) —— 第576天 (我也要出题)[html] 应用svg画一条折线图[css] 解释下为什么css中值为0时能够不写单位吗?[js] 写一个办法将字符串中的制表符全副替换为逗号[软技能] 说说你对我(面试官)的评估《论语》,曾子曰:“吾日三省吾身”(我每天屡次检查本人)。前端面试每日3+1题,以面试题来驱动学习,每天提高一点!让致力成为一种习惯,让奋斗成为一种享受!置信 保持 的力量!!!欢送在 Issues 和敌人们一起探讨学习! 我的项目地址:前端面试每日3+1【举荐】欢送跟 jsliang 一起折腾前端,零碎整顿前端常识,目前正在折腾 LeetCode,打算买通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个Star, 同时欢送微信扫码关注 前端剑解 公众号,并退出 “前端学习每日3+1” 微信群互相交换(点击公众号的菜单:交换)。 学习不打烊,充电加油只为遇到更好的本人,365天无节假日,每天早上5点纯手工公布面试题(死磕本人,愉悦大家)。心愿大家在这虚夸的前端圈里,放弃沉着,保持每天花20分钟来学习与思考。在这变幻无穷,类库层出不穷的前端,倡议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢送大家到Issues交换,激励PR,感激Star,大家有啥好的倡议能够加我微信一起交换探讨!心愿大家每日去学习与思考,这才达到来这里的目标!!!(不要为了谁而来,要为本人而来!)交换探讨欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个[Star]

November 12, 2020 · 1 min · jiezi

关于面试:高频面试题秒杀场景设计

秒杀这个话题到当初来说曾经是一个陈词滥调的话题了,不过因为又邻近一年一度的双11,而且发现前段时间无论是阿里还是腾讯一些大厂其实还是在频繁的问到这个场景题,所以还是筹备拿出来说说。 秒杀从规模上来说能够分为大秒和小秒。大秒指的是比方双11这种特定的节日,商品规模超大、价格超低、流量超大的这种类型流动,小秒个别指的是商家本人配置的一些时段类型的流动,由商家本人指定工夫上架。从模式来说还能够分为单时段秒杀和多时段秒杀。然而在这个场景里,咱们个别就是指的单时段大型秒杀。 秒杀设计要面对的压力和难度有几点: 怎么保障超高的流量和并发下零碎的稳定性?如果峰值的QPS达到几十万,面对微小的流量的压力零碎怎么设计保障不被打崩?怎么保证数据最终一致性?比方库存不能超卖,超卖了那赔本的要么就是商家要么就是平台,用户反正不背这个锅,超卖了就往年325预订。当然,波及到这种大型的流动,还须要思考到数据统计分析,总不能流动做完了,成果不晓得怎么样。 零碎架构假如往年的双11预估峰值QPS将会有50万(我轻易扯的),而依据咱们平时的教训单机8C8G的机器能够达到1000左右的QPS,那么从实践上来说咱们只有500台机器就能够抗住了,就有钱任性不行?这么设计的话只能出门右转不送了。 流量过滤实质上,参加秒杀的用户很多,然而商品的数量是无限的,真正能抢到的用户并不多,那么第一步就是要过滤掉大部分有效的流量。 流动开始前前端页面的Button置灰,避免流动未开始有效的点击产生流量前端增加验证码或者答题,避免霎时产生超高的流量,能够很好的起到错峰的成果,当初的验证码花样繁多,题库有的还要做个小学题,而且题库更新频繁,想暴力破解怕是很难。当然我晓得的还有一种人工打码的形式,不过这个也是须要工夫的,不像机器有限刷你的接口。流动校验,既然是流动,那么流动的参加用户,加入条件,用户白名单之类的要首先做一层校验拦挡,还有其余的比方用户终端、IP地址、参加流动次数、黑名单用户的校验。比方流动次要针对APP端的用户校验,那么依据参数其余端的用户将被拦挡,针对IP、mac地址、设施ID和用户ID能够对用户参加流动的次数做校验,黑名单依据平时的流动教训拦挡掉一部分羊毛党等异样用户。非法申请拦挡,做了以上拦挡如果还有用户能绕过限度,那不得不说太牛X了。比方双11零点开始还做了答题限度,那么正常人怎么也须要1秒的工夫来答题吧,就算独身30年手速我想也不能超过0.5秒了,那么针对刚好0点或者在0.5秒以内的申请就能够齐全拦挡掉。限流,假如秒杀10000件商品,咱们有10台服务器,单机的QPS在1000,那么实践上1秒就能够抢完,针对微服务就能够做限流配置,防止后续有效的流量打到数据库造成不必要的压力。针对限流还有另外一种栅栏形式限流,这是一种纯靠运气的限流形式,就是在零碎约定的申请开始的工夫内随机偏移一段时间,针对每个申请的偏移量不同,如果在偏移工夫之内就会被拦挡,反之通过。 性能优化做完有效流量的过滤,那么可能你的有效申请曾经过滤掉了90%,剩下的无效流量会大大的升高零碎的压力。之后就是须要针对零碎的性能做出优化了。 页面动态化,参加秒杀流动的商品个别都是已知的,能够针对流动页面做动态化解决,缓存到CDN。假如咱们一个页面300K大小,1千万用户的流量是多少?这些申请要申请后端服务器、数据库,压力可想而知,缓存到CDN用户申请不通过服务器,大大减小了服务器的压力。流动预热,针对流动的流动库存能够独立进去,不和一般的商品库存共享服务,流动库存流动开始前提前加载到redis,查问全副走缓存,最初扣减库存再视状况而定。独立部署,资源短缺的状况下能够思考针对秒杀流动独自部署一套环境,这套环境中能够剥离一些可能无用的逻辑,比方不必思考应用优惠券、红包、下单后赠送积分的一些场景,或者这些场景能够流动完结后异步的对立发放。这只是一个举例,实际上独自针对秒杀流动的话你必定有很多无用的业务代码是能够剥离的,这样能够进步不少性能。通过这两步之后,最终咱们的流量应该是呈漏斗状。 超卖秒杀除开高并发高流量下的服务稳定性之外,剩下的外围大略就是怎么保障库存不超卖了,也能够说要保障的是最终一致性。一般来说,针对下单和库存有两种形式: 下单即扣库存,这是最惯例的大部分的做法。然而可能在流动中会碰到第二点说到的状况。领取实现扣库存,这种设计我碰到过就是酒店行业,便宜房放进去之后被黄牛下单抢占库存导致失常用户无奈下单,而后黄牛能够用稍高的价格再售卖给用户从中牟利,所以会有在一些流动的时候采取领取胜利后才占用库存的做法。不过这种形式实现起来比较复杂,可能造成大量的有效订单,在秒杀的场景中不太实用。针对秒杀倡议抉择下单扣库存的形式,实现绝对简略而且是惯例做法。 计划 首先查问redis缓存库存是否短缺先扣库存再落订单数据,能够避免订单生成了没有库存的超卖问题扣库存的时候先扣数据库库存,再扣减redis库存,保障在同一个事务里,无论两者哪一个产生了异样都会回滚。有一个问题是可能redis扣胜利了因为网络问题返回失败,事务回滚,导致数据库和缓存不统一,这样理论少卖了,能够放到下轮秒杀去。这种做法能肯定水平上解决问题,然而也有可能会有其余问题。比方当大量申请落在同一条库存记录下来做update时,行锁导致大量的锁竞争会使得数据库的tps急剧下降,性能无奈满足要求。 另外一种做法就是排队,在服务层进行排队,针对同一个商品ID的也就是数据库是一条库存记录的做一个内存队列,串行化去扣减库存,能够肯定水平上缓解数据库的并发压力。 品质保障为了保证系统的稳定性,避免你的零碎被秒杀,一些品质监控就不得不做。 熔断限流降级,陈词滥调,依据压测状况进行限流,能够应用sentinel或者hystrix。另外前端后端都该有降级开关。监控,该上的都上,QPS监控、容器监控、CPU、缓存、IO监控等等。演练,大型秒杀事先演练少不了,不能冒冒失失的就上了吧。核查、预案,预先库存订单 金额、数量核查,是否产生超卖了?金额是否失常?都是必须的。预案能够在紧急情况下进行降级。数据统计流动做完了,数据该怎么统计? 前端埋点数据大盘,通过后盾服务的打点配合监控零碎能够通过大盘直观的看到一些流动的监控和数据离线数据分析,预先流动的数据能够同步到离线数仓做进一步的剖析统计总结总的来说,面对巨量的流量咱们的形式就是首先通过各种条件先筛选掉有效流量,进行流量错峰,而后再对现有的零碎性能做出优化,比方页面动态化,库存商品预热,也能够通过独立部署的形式和其余的环境做隔离,最初还要解决高并发下缓存一致性、库存不能超卖的问题,避免大量的并发打爆你的数据库。 一个残缺的流动从前端到后端是一个残缺的链路,两头有事先的演练工作,预先的数据分析等都是必不可少的环节。 END -

November 4, 2020 · 1 min · jiezi

关于面试:java-实现跳表skiplist及论文解读

什么是跳跃表跳表由William Pugh创造。 他在论文 《Skip lists: a probabilistic alternative to balanced trees》中具体介绍了跳表的数据结构和插入删除等操作。 跳表是一种能够用来代替均衡树的数据结构,跳表应用概率均衡而不是严格执行的均衡,因而,与等效树的等效算法相比,跳表中插入和删除的算法要简略得多,并且速度要快得多。 为什么须要?性能比拟好。 实现绝对于红黑树比较简单。 占用更少的内存。 论文解读为了学习第一手的材料,咱们先学习一下论文,而后再联合网上的文章,实现一个 java 版本的 skip-list。 William Pugh二叉树可用于示意抽象数据类型,例如字典和有序列表。 当元素以随机程序插入时,它们能够很好地工作。某些操作序列(例如按程序插入元素)产生了生成的数据结构,这些数据结构的性能十分差。 如果能够随机排列要插入的我的项目列表,则对于任何输出序列,树都将很好地工作。在大多数状况下,必须在线答复查问,因而随机排列输出是不切实际的。 均衡树算法会在执行操作时重新排列树,以放弃肯定的平衡条件并确保良好的性能。 skiplist是均衡树的一种概率代替计划。 通过征询随机数生成器来均衡skiplist。只管skiplist在最坏状况下的性能很差,然而没有任何输出序列会始终产生最坏状况的性能(就像枢轴元素随机抉择时的疾速排序一样)。 skiplist数据结构不太可能会重大失衡(例如,对于超过250个元素的字典,搜寻所破费的工夫超过预期工夫的3倍的机会少于百万分之一)。相似于通过随机插入构建的搜寻树,但不须要插入即可是随机的。 概率性地均衡数据结构比显式地保持平衡容易。 ps: 大部分程序员能够手写 skip-list,然而手写一个红黑树就要简单的多。 对于许多应用程序,skiplist比树更天然地示意,这也导致算法更简略。 skiplist算法的简略性使其更易于实现,并且在均衡树和自调整树算法上提供了显着的恒定因子速度改良。 skiplist也十分节俭空间。它们能够轻松配置为每个元素均匀须要 4/3 个指针(甚至更少),并且不须要将均衡或优先级信息与每个节点一起存储。 算法核心思想对于一个linked list来说,如果要查找某个元素,咱们可能须要遍历整个链表。 如果list是有序的,并且每两个结点都有一个指针指向它之后两位的结点(Figure 1b),那么咱们能够通过查找不超过 ⌈n/2⌉+1 个结点来实现查找。 如果每四个结点都有一个指针指向其之后四位的结点,那么只须要查看最多 ⌈n/4⌉+2 个结点(Figure 1c)。 如果所有的第(2^i)个结点都有一个指针指向其2^i之后的结点(Figure 1d),那么最大须要被查看的结点个数为 ⌈log_n2⌉,代价仅仅是将须要的指针数量加倍。 这种数据结构的查问效率很高,然而对它的插入和删除简直是不可实现的(impractical)。 接下来看下论文中的一张图: 因为这样的数据结构是基于链表的,并且额定的指针会跳过两头结点,所以作者称之为跳表(Skip Lists)。 构造从图中能够看到, 跳跃表次要由以下局部形成: 表头(head):负责保护跳跃表的节点指针。 跳跃表节点:保留着元素值,以及多个层。 层:保留着指向其余元素的指针。高层的指针越过的元素数量大于等于低层的指针,为了进步查找的效率,程序总是从高层先开始拜访,而后随着元素值范畴的放大,缓缓升高档次。 表尾:全副由 NULL 组成,示意跳跃表的开端。 skip-list 算法过程本节提供了在字典或符号表中搜寻,插入和删除元素的算法。 搜寻操作将返回与所需的键或失败的键关联的值的内容(如果键不存在)。 ...

November 2, 2020 · 4 min · jiezi

关于面试:面经面试官如果让你设计一个高并发的消息中间件你会怎么做

写在后面很多小伙伴去大厂面试,简直都会遇到一些开放式的题目,这些开放式的题目没有固定的答案,然而它可能实实在在的体现面试者较为实在的零碎设计能力和技术功底。如果你答复的比拟完满,那么,通过这种开放式题目,就可能让你从泛滥的面试者中怀才不遇。明天,咱们就一起来聊聊,去大厂面试时,一个较为常见的开放式题目:如果让你设计一个高并发的消息中间件,你会怎么做?消息中间件波及的知识点要想设计一个具备高并发的消息中间件,那么首先就要理解下消息中间件波及哪些具体的知识点。通常,设计一个良好的消息中间件须要理解的知识点如下: 生产者消费者模型。反对分布式架构。数据的高可用。音讯数据不失落。接下来,咱们就针对消息中间件来别离谈谈这些技术点。 生产者消费者模型置信很多小伙伴对于生产者和消费者模型都比拟理解了,简略的说:就是消息中间件可能使其余利用来生产音讯,也可能使其余利用来生产相应的音讯。 对于生产者和消费者模型,咱们须要思考的问题点就比拟多了。接下来,我就一步步来疏导大家进行思考。 首先,咱们来思考这样一个问题: 如果生产者生产了音讯,那么消息中间件应该怎么存储相应的数据呢? 存储在内存? 存储在磁盘? 还是同时存储在内存和磁盘中呢? 如果是将音讯数据同时存储在内存和磁盘中,咱们又该如何解决这些数据呢? 是生产者将音讯投递到消息中间件之后,咱们就立即将数据写入磁盘?还是说数据先驻留到内存,而后每隔一段时间刷到磁盘上? 如果是每隔一段时间刷到磁盘上,那咱们又要思考磁盘文件的切分问题,也就是说,须要将分成多少个磁盘文件?(总不能把所有的数据放到一个磁盘文件中吧)。如果是须要切分成多个磁盘文件,那切分的规定又是什么呢? 下面这些问题都是咱们在设计一个消息中间件时须要思考的问题。然而,这还只是一小部分问题。如果想在面试时怀才不遇,那就还须要持续往下看,还有一些重要的问题点须要留神。 如果文件依照肯定的规定切分到多个磁盘文件中了,那是不是还须要一些对于元数据的治理来标识数据的具体音讯(就像是Hadoop中的NameNode节点中存储着DataNode的元数据信息,NameNode节点通过这些元数据信息就可能更好的治理DataNode节点)?这些元数据能够包含:音讯数据的偏移量、也能够是音讯数据的惟一ID。 思考完数据的存储问题,咱们还须要思考的是:消息中间件是如何将数据投递到对应的消费者的? 在设计生产者和消费者时,还一个很重要的问题须要咱们思考:咱们在设计消息中间件时,采纳的生产模式是什么?会不会将数据平均的调配给消费者?还是会通过一些其余的规定将数据投递到消费者? 反对分布式架构如果咱们设计的消息中间件,每天会承载TB级别的数据高并发和高吞吐量的写入操作。这里,咱们就须要思考将消息中间件设计成分布式架构。 在设计分布式架构时,咱们还须要思考将存储的比拟大的数据,做成分片存储,对数据进行分片等操作。 除了这些,咱们还须要思考另外一个外围问题:对于消息中间件来说,须要反对主动扩容操作。 还有就是否反对数据分片,如何实现数据分片的扩容和主动数据负载平衡迁徙。 数据的高可用个别互联网利用的高可用,是通过本地堆内存,和一份数据在不同的服务器上都搞一个副原本实现的。此时,任何一个存储节点宕机,都不会影响整体的高可用。 音讯数据不失落此时,咱们就须要提供手动ACK的机制,也就是说:当消费者真正生产音讯结束后,向消息中间件返回“ 解决实现” 的标识,消息中间件删除相应的已解决的音讯。 然而,细化的话,这里,咱们就须要两套ACK机制: 一种ACK对应的是生产端。如果始终没有接管到ACK音讯,则须要通过生产者来从新发送一条音讯来保障生产音讯胜利。另一种ACK对应的是生产端。一旦生产解决胜利一条音讯了,必须返回一个ack给消息中间件,而后消息中间件能力删除这条音讯。否则一旦消费者宕机,就必须重发这条音讯给其余的消费者实例,保障音讯肯定会被解决胜利。明天,咱们没有聊具体的业务点,而是从整体上思考:如果实现一个消息中间件,须要咱们留神的各项知识点和专业技能!好了,明天就到这儿吧。咱们下期见! 重磅福利微信搜一搜【冰河技术】微信公众号,关注这个有深度的程序员,每天浏览超硬核技术干货,公众号内回复【PDF】有我筹备的一线大厂面试材料和我原创的超硬核PDF技术文档,以及我为大家精心筹备的多套简历模板(不断更新中),心愿大家都能找到心仪的工作,学习是一条时而郁郁寡欢,时而开怀大笑的路,加油。如果你通过致力胜利进入到了心仪的公司,肯定不要懈怠放松,职场成长和新技术学习一样,逆水行舟。如果有幸咱们江湖再见! 另外,我开源的各个PDF,后续我都会继续更新和保护,感激大家长期以来对冰河的反对!! 写在最初如果你感觉冰河写的还不错,请微信搜寻并关注「 冰河技术 」微信公众号,跟冰河学习高并发、分布式、微服务、大数据、互联网和云原生技术,「 冰河技术 」微信公众号更新了大量技术专题,每一篇技术文章干货满满!不少读者曾经通过浏览「 冰河技术 」微信公众号文章,吊打面试官,胜利跳槽到大厂;也有不少读者实现了技术上的飞跃,成为公司的技术骨干!如果你也想像他们一样晋升本人的能力,实现技术能力的飞跃,进大厂,升职加薪,那就关注「 冰河技术 」微信公众号吧,每天更新超硬核技术干货,让你对如何晋升技术能力不再迷茫!

November 1, 2020 · 1 min · jiezi

关于面试:CopyOnWriteArrayList-使用入门及源码详解

CopyOnWriteArrayList官网定义CopyOnWriteArrayList是ArrayList的线程平安变体,其中通过创立底层数组的新副原本实现所有可变操作(增加,设置等)。 这通常老本太高,然而当遍历操作大大超过渐变时,它可能比代替办法更无效,并且当您不能或不想同步遍历但须要排除并发线程之间的烦扰时十分有用。 “快照”款式迭代器办法在创立迭代器时应用对数组状态的援用。 这个数组在迭代器的生命周期中永远不会扭转,所以烦扰是不可能的,并且保障迭代器不会抛出ConcurrentModificationException。自迭代器创立以来,迭代器不会反映列表的增加,删除或更改。不反对对迭代器自身进行元素更改操作(删除,设置和增加)。这些办法抛出UnsupportedOperationException。 容许所有元素,包含null。 内存一致性成果:与其余并发汇合一样,在将对象放入CopyOnWriteArrayList之前,线程中的操作产生在从另一个线程中的CopyOnWriteArrayList拜访或删除该元素之后的操作之前。 应用例子网上这种代码大同小异。 ArrayList 版本上面来看一个列子:两个线程一个线程循环读取,一个线程批改list的值。 import java.util.ArrayList;import java.util.List;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class CopyOnWriteArrayListDemo { /** * 读线程 */ private static class ReadTask implements Runnable { List<String> list; public ReadTask(List<String> list) { this.list = list; } public void run() { for (String str : list) { System.out.println(str); } } } /** * 写线程 */ private static class WriteTask implements Runnable { List<String> list; int index; public WriteTask(List<String> list, int index) { this.list = list; this.index = index; } public void run() { list.remove(index); list.add(index, "write_" + index); } } public void run() { final int NUM = 10; List<String> list = new ArrayList<String>(); for (int i = 0; i < NUM; i++) { list.add("main_" + i); } ExecutorService executorService = Executors.newFixedThreadPool(NUM); for (int i = 0; i < NUM; i++) { executorService.execute(new ReadTask(list)); executorService.execute(new WriteTask(list, i)); } executorService.shutdown(); } public static void main(String[] args) { new CopyOnWriteArrayListDemo().run(); }}这个运行后果会报错。 ...

October 31, 2020 · 6 min · jiezi

关于面试:面试经典-ConcurrentHashMap-源码你读过吗

HashMap 的线程安全性HashMap 是线程不平安的。 为了应用线程平安的数据结构,多线程条件下,可应用 Collections.synchronizedMap 办法结构出一个同步Map,或者间接应用线程平安的 ConcurrentHashMap。 Java 7基于分段锁的ConcurrentHashMap注:本章的代码均基于JDK 1.7.0_67 数据结构Java 7中的ConcurrentHashMap的底层数据结构依然是数组和链表。 与HashMap不同的是,ConcurrentHashMap最外层不是一个大的数组,而是一个Segment的数组。 每个Segment蕴含一个与HashMap数据结构差不多的链表数组。整体数据结构如下图所示。 寻址形式在读写某个Key时,先取该Key的哈希值。 并将哈希值的高N位对Segment个数取模从而失去该Key应该属于哪个Segment,接着如同操作HashMap一样操作这个Segment。 为了保障不同的值均匀分布到不同的Segment,须要通过如下办法计算哈希值。 private int hash(Object k) { int h = hashSeed; if ((0 != h) && (k instanceof String)) { return sun.misc.Hashing.stringHash32((String) k); } h ^= k.hashCode(); h += (h << 15) ^ 0xffffcd7d; h ^= (h >>> 10); h += (h << 3); h ^= (h >>> 6); h += (h << 2) + (h << 14); return h ^ (h >>> 16);}同样为了进步取模运算效率,通过如下计算,ssize即为大于concurrencyLevel的最小的2的N次方,同时segmentMask为2^N-1。 ...

October 29, 2020 · 2 min · jiezi

关于面试:面试公司1中小型

口试详细描述一下web的session;优化一段代码 func Operator() error { if Operator1() { if Operator2() { if Operator3() { if Operator4() { } else { return OPERATORFAIL4 } } else { return OPERATORFAIL3 } } else { return OPERATORFAIL2 } } else { return OPERATORFAIL1 } return nil}nil、closed、只读、只写的channel,别离进行write和read会有什么状况产生?如何防止3的状况产生?咱们在应用channel的时候应该留神什么?给定一大堆ip范畴、国家的映射数据文件,依据ip获取国家,如下构造 1.2.0.12-1.2.1.123,CN;2.23.0.142-2.23.1.123,SG;......23.230.0.142-23.230.1.123,US;有以下3个小题: 实现一个函数,把ip转换为一种可比拟的数,并且跟ip一样是放弃原来的大小排序;依据下面实现的函数,如何设计数据库表以及设计sql,如何疾速的以ip查到国家;忘了;给定一组整数,输入指定和为某个数的多对后果;以下的函数输入 func main() { for i := 0; i < 10; i++ { go func() { fmt.Println(i) }() } select {}}如何实现只用2个goroutine, 打印5个随机数;一面 ...

October 21, 2020 · 1 min · jiezi

关于面试:ReentrantLock-可重入锁这样学面试没烦恼下班走得早

为什么须要 ReentrantLock ?既生 synchronized,何生 ReentrantLock? 每一个接触过多线程的 java coder 必定都晓得 synchronized 关键字,那为什么还须要 ReentrantLock 呢? 其实这就是 ReentrantLock 与 synchronized 比照的劣势问题: (1)ReentrantLock 应用起来更来更加灵便。咱们在须要管制的中央,能够灵便指定加锁或者解锁。 这能够让加锁的范畴更小,记住老马的一句话,更小往往意味着更快。 (2)ReentrantLock 提供了偏心锁、非偏心锁等多种办法个性,这些都是 synchronized 关键字无奈提供的。 接下来,就让咱们一起来学习一下 ReentrantLock 可重入锁吧。 ReentrantLock 应用线程定义创立一个可重入锁线程。 /** * @author 老马啸东风 */public class ReconnectThread extends Thread { /** * 申明可重入锁 */ private static final ReentrantLock reentrantLock = new ReentrantLock(); /** * 用于标识以后线程 */ private String name; public ReconnectThread(String name) { this.name = name; } @Override public void run() { reentrantLock.lock(); try { for (int i = 0; i < 5; i++) { System.out.println(name+" "+i+" times"); Thread.sleep(1000); } } catch (Exception e) { e.printStackTrace(); } finally { reentrantLock.unlock(); } }}测试Test/** * @author 老马啸东风 */public static void main(String[] args) { Thread one = new ReconnectThread("one"); Thread two = new ReconnectThread("two"); one.start(); two.start();}result依据后果可知。两个必须要期待另外一个执行实现能力运行。 ...

October 21, 2020 · 4 min · jiezi

关于面试:js基础常问面试题

1.JS中let和const有什么用?在古代js中,let&const是创立变量的不同形式。 在晚期的js中,咱们应用var关键字来创立变量。 let&const关键字是在ES6版本中引入的,上面咱们来看下var let const 的区别: var申明变量存在变量晋升,let和const不存在变量晋升 console.log(a); // undefined ===> a已申明还没赋值,默认失去undefined值var a = 1;console.log(b); // 报错:b is not defined ===> 找不到b这个变量let b = 2;console.log(c); // 报错:c is not defined ===> 找不到c这个变量const c = 3;let、const属于块级作用域顾名思义,就是只在以后代码块起作用,let和const区别:const用来申明一个只读的常量, 一旦申明,常量的值不可扭转,申明时必须设置初始化值,否则会报错 块级作用域的长处1、防止内层变量笼罩外层变量2、防止用来计数的循环变量泄露为全局变量3、引入了块级作用域,容许在块级作用域之中申明函数 2. module.exports 和 exports 之间有什么区别?module和exports是Node.js给每个js文件内置的两个对象。能够通过console.log(module)和console.log(exports)打印进去。如果你在main.js中写入上面两行,而后运行$ node main.js: console.log(exports);//输入:{}console.log(module);//输入:Module {..., exports: {}, ...} (注:...代表省略了其余一些属性) 从打印咱们能够看出,module.exports和exports一开始都是一个空对象{},实际上,这两个对象指向同一块内存。这也就是说module.exports和exports是等价的(有个前提:不去扭转它们指向的内存地址)。 例如:exports.age = 18和module.export.age = 18,这两种写法是统一的(都相当于给最后的空对象{}增加了一个属性,通过require失去的就是{age: 18})。 3. JS 中 == 和 === 区别是什么?1、对于string,number等根底类型,==和===有区别 1)不同类型间比拟,==之比拟“转化成同一类型后的值”看“值”是否相等,===如果类型不同,其后果就是不等。2)同类型比拟,间接进行“值”比拟,两者后果一样。 2、对于Array,Object等高级类型,==和===没有区别 ...

October 21, 2020 · 2 min · jiezi

关于面试:前端面试2020-面试的心得

花一秒钟就看透事物本质的人,和花半辈子都看不清事物本质的人,注定是截然不同的命运。——《教父》到职 1 周多,到当初为止大大小小面试了 12 家,教训积攒了不少,记录下心得。 技术面80% 公司都有口试题,所以须要大量刷题。你常识量多大都好,不刷题就是不行。长期的推理很难在 30 分钟内实现 5 个选择题 + 2 个简答题 + 1 到 2 个编程题。简历上要写我的项目难点,什么后盾治理、国际化、看源码曾经不吃香,我说的是没个几天几夜,或者根底不好就搞不进去的那种。话不要说的太死,或者太强硬。一些技术点、观点能够让面试官补充,让他有点话说,达到交换的目标。记住他在挑一个友善的共事。适当的称誉下面试官表达清晰、有气场,有奇效。电话面试时候,要学会“舞弊”,用本子列一下自我介绍重点和我的项目重点,力求逻辑清晰。治理面 & HR 面老东家多不好都好,好话也是半点说不得。到职的理由是考查你的性情的,尽量踊跃侧面些(比方寻求更好的时机,想要奋斗。互联网公司都喜爱“奋斗”的人)。对个别的公司,报期待薪资时候不要太离谱,比之前的高 30-40% 就好。听猎头说,很多公司都在管制工资涨幅,JD 上写的 20-40K 看看就好。当然一些厉害的公司就不要报的底了,比方腾讯,报低了就是看不起公司 XD。

October 20, 2020 · 1 min · jiezi

关于面试:在重写equals方法的时候为什么需要重写hashCode方法

在重写equals办法的时候为什么须要重写hashCode办法?生存平静而美妙。 明天聊一聊面试题 《在重写equals办法的时候为什么须要重写hashCode办法?》(equals办法与hashCode办法的区别与分割) 编程中常常会用到HashMap,HashSet等数据结构。这个数据结构都是由键值对组成的,如果键值对的键是对象,程序会依据对象返回的 hashCode 来确定值所在的地位。咱们通常认为两个内容雷同的对象是相等的,并通过重写 equals 办法来达到这个目标。因为对象默认返回 hashCode 是对象的地址值,当咱们把下面相等的对象作为 HashMap 的键的时候,程序会定位到两个不同的地位的值,这种后果其实是不适合的。这也就是为什么咱们在重写 equals 办法的时候,往往须要重写 hashCode,让相等的对象返回雷同的 hashCode 的起因。

October 15, 2020 · 1 min · jiezi

关于面试:项目实战Java开发微服务畅购商城实战全357集大项目附代码和课件

畅购是属于B2C电商,零碎后盾包含治理后盾和网站前台。 我的项目的治理后盾采纳前后 端拆散的技术架构,后端微服务采纳SmngBOOt、SprindClound、SmngMVC ,MyBatiS框架, 前端采纳VUe.jS + ElementUI.前台包含:首页零碎、商家首页、商品 具体页、购物车零碎、订单零碎、领取零碎、会员零碎、评论零碎、商品搜寻、秒 杀、用户核心等多个零碎组成。 我的项目特色 畅购电商我的项目采纳docke服务器部署,对模板渲染、搜寻、缓存、音讯队列、分布式事 务等内容都有深层次的利用。 网站后盾采纳前后端拆散技术,前端采纳以后支流的 VUe.jS + ElementUI,网站后盾采纳JWT技术实现微服务鉴杈,采纳SmngBOOt SprindClound 微服务技术架构, 采纳《黑马程序员代码生成器》生成工程 代码,晋升开发效率,采纳RabbitMQ作为消息中间件,采纳GateWay实现微服务网 关,采纳EIasticSearch 实现商品搜素,零碎解说redis的哨兵模式、缓存击穿、缓存雪 崩等解决方案,采纳ELK作为分布式目志零碎,采纳继续集成工具 JenKins, 应用限 流解决高并发问题,应用CAS v5.3作为单点登陆零碎,采纳分布式事务框架- LCN,使用了RediS队列等技术实现秒杀零碎。 视频地址:https://www.bilibili.com/vide... 关注vx公众号:【不止于编程】在首页回复:畅购商城 获取视频课件、源码、视频。

October 14, 2020 · 1 min · jiezi

关于面试:非常全面阿里巴巴Java面试题及答案2020年6月份

一、阿里技术一面Java IO流的层次结构?请说出罕用的异样类型?SKU的全称是什么,SKU与SPU的区别及关系?FileInputStream在应用完当前,不敞开流,想二次应用能够怎么操作?设计一个分步式登录零碎?Spring加载过程?本人有没有写过相似Spring这样的AOP事务?Java中 try..catch敞开流的语法糖?如何设计一个秒杀零碎?要思考什么?有没有遇到进线上GC,呈现的症状是什么样的,怎么解决的?spring的加载过程?atomic与 volatile的区别?Thread的 notify给notifyAll的区别?notifiy是唤醒的那一个线程?Thread.sleep唤醒当前是否须要从新竞争?单例有多少种写法?有什么区别?你罕用哪一种单例,为什么用这种?问一个Thread.join相干的问题?商品相干模块零碎怎么设计数据模型?写一个JAVA死锁的列子?如何解决死锁?GC回收算法,及实现原理?HashMap数据存储构造? key反复了怎么办?是如何解决的?Spring AOP的实现原理,底层用什么实现的?二、阿里技术二面电话面试次要考查3块内容: Java的相干基础知识,开源框架的原理,JVM,多线程,高并发,中间件等;之前我的项目经验,使用的技术,遇到的问题,如何解决,集体有什么播种和成长;对于技术的激情(平时是否看些技术书籍,逛论坛,写博客,写源代码或程序等);三、JAVA开发技术面试可能问到的问题咱们次要考核的是网络nio分布式数据库高并发大数据自定义表格的实现?动静表单设计?in-jvm(必考)以及jmm缓存模型如何调优?罕用的RPC框架nio和io并发编程,设计模式地图组件?hashmap有什么破绽会导致他变慢?如何给hashmap的key对象设计他的hashcode?泛型通配符?在什么状况下应用?后端方面:redis?分布式框架dubbo(阿里巴巴开源框架)?设计模式?场景式的问题:秒杀,能列出常见的排队、验证码、库存扣减形式对系统高并发的影响?能依据理论的须要构建缓存构造进步进步网站的访问速度,纯熟应用ehcache、oscache,理解memcache。理解基于dns轮询的负载平衡,纯熟配置web服务器实现负载平衡,程序级能综合应用基于hash或取模等伎俩实现软负载。相熟分布式数据库设计和优化技术,纯熟应用mysql、oracle、SqlServer等支流数据库,相熟hadoop hbase mangodb redis ehcache、oscache memcache。对于大数据量的数据库解决采纳分表分库、数据库读写拆散、建设缓存等伎俩优化性能。熟练掌握lucene,能基于lucene开发大型的搜索引擎,并能用lucene来改善和优化数据库的like查问。四、JAVA方向技术考察点(补充):把握Java编程语言,蕴含io/nio/socket/multi threads/collection/concurrency等性能的应用;熟练掌握jvm(sun hotspot和ibm j9)内存模型、gc垃圾回收调优等技能;精通JVM,JMM,MVC架构,纯熟应用struts2。纯熟应用spring、struts、ibatis构建利用零碎。纯熟应用Servlet,jsp,freemark等前端技术。纯熟应用axis搭建基于SOAP协定的WebService服务接口。纯熟应用MAVEN构建我的项目工程。纯熟应用tomcat等web服务。纯熟应用mysql等关系型数据库,相熟mysql集群搭建。纯熟应用redis等NOSQL技术。相熟tcp、http协定。相熟nginx、haproxy等配置。相熟javascript、ajax等技术。相熟支流分布式文件系统FastDFS等。相熟JMS,可纯熟应用ActiveMQ。底层计算机了解内存治理/数据挖掘零碎可靠性和可用性如何了解~jsp和sever lap比照数据库到界面,字符集转化基栈jvm优化cup高的时候如果剖析和监控java curb突出细节问题分布式缓存文档如何分流迁徙数据库垂直宰割高并发如何解决前端高并发应用层LB设计load balance负载平衡防网络攻击数据日志事件监控后告诉数据库事务实现的底层机制字符串空格输出的网络攻击Quartz框架的底层原理数据库同步中不通过数据库引擎间接读日志等形式同步数据五、我的项目局部缓存的应用,如果当初须要实现一个简略的缓存,供搜寻框中的ajax异步申请调用,应用什么构造?内存中的缓存不能始终存在,用什么算法定期将搜寻权重较低的entry去掉?TCP如何保障安全性红黑树的问题,B+数JDK1.8中对HashMap的加强,如果一个桶上的节点数量过多,链表+数组的构造就会转换为红黑树。我的项目中应用的单机服务器,如果将它部署成分布式服务器?MySQL的常见优化形式、定为慢查问手写一个线程平安的单例模式六、进阿里必会常识:算法和数据结构数组、链表、二叉树、队列、栈的各种操作(性能,场景)二分查找和各种变种的二分查找各类排序算法以及复杂度剖析(快排、归并、堆)各类算法题(手写)了解并能够剖析工夫和空间复杂度。动静布局(口试回回有。。)、贪婪。红黑树、AVL树、Hash树、Tire树、B树、B+树。图算法(比拟少,也就两个最短门路算法了解吧)计算机网络OSI7层模型(TCP4层)每层的协定url到页面的过程HTTPhttp/https 1.0、1.1、2.0get/post以及幂等性http协定头相干网络攻击(CSRF、XSS)TCP/IP三次握手、四次挥手拥塞管制(过程、阈值)流量管制与滑动窗口TCP与UDP比拟子网划分(个别只有口试有)DDos攻打(B)IO/NIO/AIO三者原理,各个语言是怎么实现的NettyLinux内核select poll epoll数据库(最多的还是mysql,Nosql有redis)索引(包含分类及优化形式,生效条件,底层构造)sql语法(join,union,子查问,having,group by)引擎比照(InnoDB,MyISAM)数据库的锁(行锁,表锁,页级锁,意向锁,读锁,写锁,乐观锁,乐观锁,以及加锁的select sql形式)隔离级别,顺次解决的问题(脏读、不可反复读、幻读)事务的ACIDB树、B+树优化(explain,慢查问,show profile)数据库的范式。分库分表,主从复制,读写拆散。Nosql相干(redis和memcached区别之类的,如果你相熟redis,redis还有一堆要问的)操作系统:过程通信IPC(几种形式),与线程区别OS的几种策略(页面置换,过程调度等,每个外面有几种算法)互斥与死锁相干的linux常用命令(问的时候都会给具体某一个场景)Linux内核相干(select、poll、epoll)编程语言(这里只说Java):把我之后的面通过一遍,Java感觉笼罩的就差不多了,不过上面还是分个类。Java根底(面向对象、四个个性、重载重写、static和final等等很多货色)汇合(HashMap、ConcurrentHashMap、各种List,最好联合源码看)并发和多线程(线程池、SYNC和Lock锁机制、线程通信、volatile、ThreadLocal、CyclicBarrier、Atom包、CountDownLatch、AQS、CAS原理等等)JVM(内存模型、GC垃圾回收,包含分代,GC算法,收集器、类加载和双亲委派、JVM调优,内存透露和内存溢出)IO/NIO相干反射和代理、异样、Java8相干、序列化设计模式(罕用的,jdk中有的)Web相干(servlet、cookie/session、Spring)七、面试技巧1、答非所问: 感觉到答案说进去对方会不待见的时候,能够这么做:有关联性的答非所问,留神强调本人的想法,争取让面试官可能共情,比方深圳的房价能够引人共情、电商相干的大平台、稳固、有回升空间等。 2、面试的状态很重要: 两个例子,上月一个胜利offer的候选人,非互联网背景,公司也不是一线的,然而面试时体现出对阿里很强烈的趣味,HR预先顺便向咱们提到,对这位候选人印象很粗浅; 另一位明天刚挂的候选人,两轮技术都是一举拿下,最初HR面挂了,HR给咱们的反馈是,候选人刚从本人的守业公司到职,貌似情绪很高涨,对本人也没什么想法。 综上所述,面试时既不要气宇轩昂,过于被动,也不要过于夸大,而是在于展示本人对一个不错机会的尊重和争取,让面试官感觉你对他们,对这个岗位有很大的趣味。 答案获取,请关注公众号【不止于编程】,回复:阿里巴巴面试 近300页文档,图文并茂,还请你点个赞????

October 14, 2020 · 1 min · jiezi

关于面试:500份大厂面试题依旧免费领

十一假期前咱们做了第一波面试题免费送500份分分钟被领空十一假期后支付面试题小伙伴来反馈就是因为支付了面试题查漏补缺,欠缺知识点顺利get到大厂offer啦第二波大厂面试题就牵强附会的来袭 本期面试题-腾讯同样只有500这一期还是免费送助你圆大厂梦也助你盘点本人的知识库 面试交换群对于面试那些事儿不定期的岗位举荐外部福利等你一起来见证 第三波面试题已在路上请期待 流动工夫2020 年10 月 13 日 ↓2020 年10 月 18 日 流动规定关注公众号,即刻支付仅限500份 更多精彩内容请增加HR小姐姐

October 13, 2020 · 1 min · jiezi

关于面试:2020年Android面试高频知识点小结V10

前言耿直2020金九银十,第一次换工作或是面试候选人,咱们都会对面试常识做一次总结梳理,毕竟开发技术无边界,不同人对技术的解读不同。文章总结了最近大半年中的面试考查点V1.0,心愿对你有所帮忙。注:整顿中有反复的知识点,阐明频率较高,同时也是有不同角度的答复,也同时帮你更全面的意识。 面试倡议:算法、根底是敲门砖,我的项目是试金石,良好的面试形象是加分项。 举荐:2020年 中级Android面试总结 Android面试指南 — 算法面试心得 Android性能优化前因后果总结 Android面试系列 快手,字节跳动,百度,美团Offer之旅(Android面经分享)| 掘金技术征文 一、JAVA根底1.synchronized的润饰对象当synchronized用来润饰静态方法或者类时,将会使得这个类的所有对象都是共享一把类锁,导致线程阻塞,所以这种写法肯定要躲避 无论synchronized关键字加在办法上还是对象上,如果它作用的对象是非动态的,则它获得的锁是对象;如果synchronized作用的对象是一个静态方法或一个类,则它获得的锁是对类,该类所有的对象同一把锁。 每个对象只有一个锁(lock)与之相关联,谁拿到这个锁谁就能够运行它所管制的那段代码。 实现同步是要很大的零碎开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。 2. try{}catch{}finally中的执行程序任何执行try 或者catch中的return语句之前,都会先执行finally语句,如果finally存在的话。如果finally中有return语句,那么程序就return了,所以finally中的return是肯定会被return的, 编译器把finally中的return实现为一个warning。 上面是个测试程序public class FinallyTest { public static void main(String[] args) { System.out.println(test());; } static int test() { int x = 1; try { x++; return x; } finally { ++x; } }}运行后果:2 阐明:在try语句中,在执行return语句时,要返回的后果曾经筹备好了,就在此时,程序转到finally执行了。在转去之前,try中先把要返回的后果寄存到不同于x的局部变量中去,执行完finally之后,在从中取出返回后果,因而,即便finally中对变量x进行了扭转,然而不会影响返回后果。它应该应用栈保留返回值。 3. JAVA中的死锁JAVA中的ArrayList是否是线程平安为什么ArrayList线程不平安?不平安为什么要应用?如何解决线程不平安?首先说一下什么是线程不平安:线程平安就是多线程拜访时,采纳了加锁机制,当一个线程拜访该类的某个数据时,进行爱护,其余线程不能进行拜访直到该线程读取完,其余线程才可应用。不会呈现数据不统一或者数据净化。线程不平安就是不提供数据拜访爱护,有可能呈现多个线程先后更改数据造成所失去的数据是脏数据。List接口上面有两个实现,一个是ArrayList,另外一个是vector。 从源码的角度来看,因为Vector的办法前加了,synchronized 关键字,也就是同步的意思,sun公司心愿Vector是线程平安的,而心愿arraylist是高效的,毛病就是另外的长处。 。说下原理:一个 ArrayList ,在增加一个元素的时候,它可能会有两步来实现: 在 Items[Size] 的地位寄存此元素;增大 Size 的值。 在单线程运行的状况下,如果 Size = 0,增加一个元素后,此元素在地位 0,而且 Size=1; 而如果是在多线程状况下,比方有两个线程,线程 A 先将元素寄存在地位 0。然而此时 CPU 调度线程A暂停,线程 B 失去运行的机会。线程B也向此 ArrayList 增加元素,因为此时 Size 依然等于 0 (留神哦,咱们假如的是增加一个元素是要两个步骤哦,而线程A仅仅实现了步骤1),所以线程B也将元素寄存在地位0。而后线程A和线程B都持续运行,都减少 Size 的值。 那好,当初咱们来看看 ArrayList 的状况,元素实际上只有一个,寄存在地位 0,而 Size 却等于 2。这就是“线程不平安”了。 ...

October 12, 2020 · 9 min · jiezi

关于面试:进程和线程的区别是什么

本文参考码农翻身公众号文章,并做了适当的调整和总结。依照历史的脉络,执行程序的形式顺次经验了批处理,过程和线程三个阶段,本文依照这个程序,并以故事的模式来解释过程与线程的区别。 批处理很久很久以前,有两个程序,暂且称他们为旺财和小强。 旺财和小强这两个程序都很长,每个都有十几万行。 他们两个的人生价值就是到CPU下来运行,把运行后果通知人类。 CPU是稀缺资源,只有一个,他们俩必须排着队,轮流应用。 旺财从头到尾执行完了,让出CPU, 让小强从头儿去执行。 人类把这种解决形式叫做批处理。 过程长久以来,两人相安无事。 起初CPU的速度越来越快, 远远超过了内存,硬盘的读写速度。 人类想到,这批处理零碎的效率有点低啊,你看当小强须要从硬盘上读取数据的时候,CPU也始终在期待,这是多大的节约啊!这时候齐全能够让旺财来运行一下嘛! 当然,得保留好小强的执行现场:具体执行到那一行程序指令了, 函数调用到什么档次了,每个函数调用都有什么样的参数,CPU寄存器中的值..... 等等这一系列货色。 如果不把小强的执行现场给保留下来,等到小强的数据从硬盘读完了,就没法回到中断处来继续执行了。 这个执行现场,再加上小强的代码,就是一个执行中的程序,被称为“过程” 。 旺财和小强在运行的时候,也被革新成了过程。 人类还规定:过程不能长时间占据CPU, 只能在CPU上执行一小会儿,而后马上切换到别的过程去执行。 这样,通过引入过程和规定每个过程在CPU上的最长执行工夫,极大的缓解了CPU节约的问题,同时过程也自然而然的成为了资源分配的根本单元。 线程起初的起初,旺财有了界面,还能拜访网络,每当它联网的时候(这也是个十分十分耗时的操作),就得把CPU让给小强。 即便旺财再次被调度执行,因为网络数据还没有返回,他必须期待,什么事件都做不了,在人类看来,界面根本无法操作,旺财不响应了!气得人类常常把旺财kill掉。 旺财心里苦,他很纳闷小强怎么就没有问题,小强不是要读写硬盘吗? 那也是很慢的操作啊。 小强说:“你傻啊,外部只有一个执行的流程,一遇到耗时的操作就得期待,你看看我,外部搞了两个执行流程(线程),一个用来读写硬盘(T1),另外一个解决界面(T2)。我和操作系统磋商好了,如果T1在读写硬盘, 就能够调度我的T2来执行,这样界面至多还能够操作。 ” 旺财觉得很有意思,也采纳了相似方法。 于是,一个过程中至多有一个执行的流程(主线程),也能够开启新的执行流程(线程)。 这样,通过在过程中引入线程并和操作系统磋商以线程为根本的调度单位,就解决了领有界面的过程在进行耗时操作时,无奈响应的问题。 总结批处理就是程序一个一个排着队执行。通过引入过程和规定每个过程在CPU上的最长执行工夫,极大的缓解了CPU节约的问题,同时过程也自然而然的成为了资源分配的根本单元。通过在过程中引入线程并和操作系统磋商以线程为根本的调度单位,就解决了领有界面的过程在进行耗时操作时,无奈响应的问题。过程切换波及到资源的重新分配,所以其工夫损耗远远大于线程切换(多个线程共享过程的资源)

October 8, 2020 · 1 min · jiezi

关于面试:面试你知道MyBatis执行过程之初始化是如何执行的吗

该系列文章收录在公众号【Ccww技术博客】,原创技术文章早于博客推出前言在理解MyBatis架构以及核心内容剖析后,咱们能够钻研MyBatis执行过程,包含 MyBatis初始化SQL执行过程而且在面试会问到一下对于MyBatis初始化的问题,比方: Mybatis须要初始化哪些?MyBatis初始化的过程?MyBatis初始化在 MyBatis 初始化过程中,会加载 mybatis-config.xml 配置文件、Mapper.xml映射配置文件以及 Mapper 接口中的注解信息,解析后的配置信息会造成相应的对象并保留到 Configuration 对象中。初始化过程能够分成三局部: 解析mybatis-config.xml 配置文件 SqlSessionFactoryBuilderXMLConfigBuilderConfiguration解析Mapper.xml映射配置文件 XMLMapperBuilder::parse()XMLStatementBuilder::parseStatementNode()XMLLanguageDriverSqlSourceMappedStatement解析Mapper接口中的注解 MapperRegistryMapperAnnotationBuilder::parse()解析mybatis-config.xml 配置文件MyBatis 的初始化流程的入口是 SqlSessionFactoryBuilder::build(Reader reader, String environment, Properties properties) 办法,看看具体流程图: public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { try { XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { inputStream.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } } }首先会应用XMLConfigBuilder::parser()解析mybatis-config.xml 配置文件, ...

September 23, 2020 · 5 min · jiezi

关于面试:面试为了进阿里必须掌握HashMap原理和面试题图解版一

该系列文章收录在公众号【Ccww技术博客】,原创技术文章早于博客推出前言汇合在根底面试中是必备可缺的一部分,其中重要的HashMap更是少不了,那面试官会面试中发问那些问题呢,这些在JDK1.7和1.8有什么区别?? HashMap的底层原理HashMap的hash哈希函数的设计原理,以及HashMap下标获取形式?HashMap扩容机制,hashMap中什么时候须要进行扩容,扩容resize()又是如何实现的hashMap中put是如何实现的 ,JDK1.7和1.8有什么区别?hashMap中get是如何实现的其余波及问题 HashMap具备的个性为什么Hash的底层数据长度总为2的N次方?如果输出值不是2的幂比方10会怎么样?加载因子为什么是 0.75?哈希表如何解决Hash抵触当有哈希抵触时,HashMap 是如何查找并确认元素的?HashMap 是线程平安的吗,为什么不是线程平安的?1. HashMap的底层原理JDK1.7应用的是数组+ 单链表的数据结构。JDK1.8之后,应用的是数组+链表+红黑树的数据结构 HashMap数据结构图(jdk1.8) //解决hash抵触,链表转成树的阈值,当桶中链表长度大于8时转成树 static final int TREEIFY_THRESHOLD = 8;//进行resize操作时,若桶中数量少于6则从树转成链表static final int UNTREEIFY_THRESHOLD = 6;/* 当须要将解决 hash 抵触的链表转变为红黑树时,须要判断下此时数组容量,若是因为数组容量太小(小于 MIN_TREEIFY_CAPACITY )导致的 hash 抵触太多,则不进行链表转变为红黑树操作,转为利用 resize() 函数对 hashMap 扩容 */static final int MIN_TREEIFY_CAPACITY = 64;从HashMap常量中能够看出,当链表的深度达到8的时候,也就是默认阈值TREEIFY_THRESHOLD=8,就会主动扩容把链表转成红黑树的数据结构来把工夫复杂度从O(n)变成O(logN)进步了效率,而且当进行resize操作时,若桶中数量少于6则从树转成链表。 那为什么数据结构须要从JDK1.7换成JDK1.8的数组+链表+红黑树?在JDK1.7中,当雷同的hash值时,HashMap一直地产生碰撞,那么雷同key地位的链表就会一直增长,当查问HashMap的相应key值的Vaule值时,就会去循环遍历这个超级大的链表,查问性能十分低下。 但在JDK1.8当链表超过8个节点数时,将会让红黑树来代替链表,查问性能失去了很好的晋升,从原来的是O(n)到O(logn)。 2. HashMap的hash哈希函数的设计原理,以及HashMap下标获取 hash &(n - 1)?hash哈希函数的设计原理static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}首先获取hashcode,一个32位的int值而后将hashcode左移16位的值进行与或,行将高位与低位进行异或运算,缩小碰撞机率。 ...

September 16, 2020 · 3 min · jiezi

关于面试:面试Kafka常见面试问题总结

现如今,Kafka已不再是一个单纯的音讯队列零碎。Kafka是一个分布式的流解决平台,被越来越多的公司应用,Kafka能够被用于高性能的数据管道,流解决剖析,数据集成等场景。本文分享总结了几个Kafka常见的面试问题,心愿对你有所帮忙。次要包含以下内容: Kafka是如何保障数据不失落的?如何解决Kafka数据失落问题?Kafka能够保障永恒不失落数据吗?如何保障Kafka中的音讯是有序的?如何确定Kafka主题的分区数量?如何调整生产环境中Kafka主题的分区数量?如何重均衡Kafka集群?如何查看消费者组是否存在滞后生产?Q1:Kafka是如何保障数据不失落的?该问题曾经成为了Kafka面试的常规,如同Java的HashMap,属于高频呈现的面试问题。那么,咱们该怎么了解这个问题呢?问题是Kafka如何保障数据不失落,即Kafka的Broker提供了什么机制保证数据不失落的。 其实对于Kafka的Broker而言,Kafka 的复制机制和分区的多正本架构是Kafka 可靠性保障的外围。把音讯写入多个正本能够使Kafka 在产生解体时仍能保障音讯的持久性。 搞清楚了问题的外围,再来看一下该怎么答复这个问题:次要包含三个方面 1.Topic 正本因子个数:replication.factor >= 32.同步正本列表(ISR):min.insync.replicas = 2 3.禁用unclean选举: unclean.leader.election.enable=false 上面将会逐渐剖析下面的三个配置: 正本因子Kafka的topic是能够分区的,并且能够为分区配置多个正本,该配置能够通过replication.factor参数实现。Kafka中的分区正本包含两种类型:领导者正本(Leader Replica)和追随者正本(Follower Replica),每个分区在创立时都要选举一个正本作为领导者正本,其余的正本主动变为追随者正本。在 Kafka 中,追随者正本是不对外提供服务的,也就是说,任何一个追随者正本都不能响应消费者和生产者的读写申请。所有的申请都必须由领导者副原本解决。换句话说,所有的读写申请都必须发往领导者正本所在的 Broker,由该 Broker 负责解决。追随者正本不解决客户端申请,它惟一的工作就是从领导者正本异步拉取音讯,并写入到本人的提交日志中,从而实现与领导者正本的同步。 一般来说,正本设为3能够满足大部分的应用场景,也有可能是5个正本(比方银行)。如果正本因子为N,那么在N-1个broker 生效的状况下,依然可能从主题读取数据或向主题写入数据。所以,更高的正本因子会带来更高的可用性、可靠性和更少的故障。另一方面,正本因子N须要至多N个broker ,而且会有N个数据正本,也就是说它们会占用N倍的磁盘空间。理论生产环境中个别会在可用性和存储硬件之间作出衡量。 除此之外,正本的散布同样也会影响可用性。默认状况下,Kafka会确保分区的每个正本散布在不同的Broker上,然而如果这些Broker在同一个机架上,一旦机架的交换机产生故障,分区就会不可用。所以倡议把Broker散布在不同的机架上,能够应用broker.rack参数配置Broker所在机架的名称。 同步正本列表In-sync replica(ISR)称之为同步正本,ISR中的正本都是与Leader进行同步的正本,所以不在该列表的follower会被认为与Leader是不同步的。那么,ISR中存在是什么正本呢?首先能够明确的是:Leader正本总是存在于ISR中。而follower正本是否在ISR中,取决于该follower正本是否与Leader正本放弃了“同步”。 Kafka的broker端有一个参数replica.lag.time.max.ms, 该参数示意follower正本滞后与Leader正本的最长工夫距离,默认是10秒。这就意味着,只有follower正本落后于leader正本的工夫距离不超过10秒,就能够认为该follower正本与leader正本是同步的,所以哪怕以后follower正本落后于Leader正本几条音讯,只有在10秒之内赶上Leader正本,就不会被踢出出局。 能够看出ISR是一个动静的,所以即使是为分区配置了3个正本,还是会呈现同步正本列表中只有一个正本的状况(其余正本因为不可能与leader及时放弃同步,被移出ISR列表)。如果这个同步正本变为不可用,咱们必须在可用性和一致性之间作出抉择(CAP实践)。 依据Kafka 对可靠性保障的定义,音讯只有在被写入到所有同步正本之后才被认为是已提交的。但如果这里的“所有正本”只蕴含一个同步正本,那么在这个正本变为不可用时,数据就会失落。如果要确保已提交的数据被写入不止一个正本,就须要把最小同步正本数量设置为大一点的值。对于一个蕴含3 个正本的主题分区,如果min.insync.replicas=2 ,那么至多要存在两个同步正本能力向分区写入数据。 如果进行了下面的配置,此时必须要保障ISR中至多存在两个正本,如果ISR中的正本个数小于2,那么Broker就会进行承受生产者的申请。尝试发送数据的生产者会收到NotEnoughReplicasException异样,消费者依然能够持续读取已有的数据。 禁用unclean选举抉择一个同步正本列表中的分区作为leader 分区的过程称为clean leader election。留神,这里要与在非同步正本当选一个分区作为leader分区的过程辨别开,在非同步正本当选一个分区作为leader的过程称之为unclean leader election。因为ISR是动静调整的,所以会存在ISR列表为空的状况,通常来说,非同步正本落后 Leader 太多,因而,如果抉择这些正本作为新 Leader,就可能呈现数据的失落。毕竟,这些正本中保留的音讯远远落后于老 Leader 中的音讯。在 Kafka 中,选举这种正本的过程能够通过Broker 端参数 unclean.leader.election.enable 管制是否容许 Unclean 领导者选举。开启 Unclean 领导者选举可能会造成数据失落,但益处是,它使得分区 Leader 正本始终存在,不至于进行对外提供服务,因而晋升了高可用性。反之,禁止 Unclean Leader 选举的益处在于保护了数据的一致性,防止了音讯失落,但就义了高可用性。分布式系统的CAP实践说的就是这种状况。 可怜的是,unclean leader election的选举过程仍可能会造成数据的不统一,因为同步正本并不是齐全同步的。因为复制是异步实现的,因而无奈保障follower能够获取最新消息。比方Leader分区的最初一条音讯的offset是100,此时正本的offset可能不是100,这受到两个参数的影响: replica.lag.time.max.ms:同步正本滞后与leader正本的工夫zookeeper.session.timeout.ms:与zookeeper会话超时工夫简而言之,如果咱们容许不同步的正本成为leader,那么就要承当失落数据和呈现数据不统一的危险。如果不容许它们成为leader,那么就要承受较低的可用性,因为咱们必须期待原先的领袖复原到可用状态。 ...

September 12, 2020 · 1 min · jiezi

关于面试:答面试官问如何防超卖有几种实现方式

场景 第一种办法 乐观锁乐观并发管制(又名“乐观锁”,Pessimistic Concurrency Control,缩写“PCC”)是一种并发管制的办法。它能够阻止一个事务以影响其余用户的形式来批改数据。如果一个事务执行的操作读某行数据利用了锁,那只有当这个事务把锁开释,其余事务才可能执行与该锁抵触的操作。乐观并发管制次要用于数据争用强烈的环境,以及产生并发抵触时应用锁爱护数据的老本要低于回滚事务的老本的环境中。 简而言之,乐观锁次要用于爱护数据的完整性。当多个事务并发执行时,某个事务对数据利用了锁,则其余事务只能等该事务执行完了,能力进行对该数据进行批改操作。 update goods set num = num - 1 WHERE id = 1001 and num > 0假如当初商品只剩下一件了,此时数据库中 num = 1; 但有100个线程同时读取到了这个 num = 1,所以100个线程都开始减库存了。 但你会最终会察觉,其实只有一个线程减库存胜利,其余99个线程全副失败。 须要留神的是,FOR UPDATE失效须要同时满足两个条件时才失效: 数据库的引擎为 innoDB操作位于事务块中(BEGIN/COMMIT)乐观锁采纳的是「先获取锁再拜访」的策略,来保障数据的平安。然而加锁策略,依赖数据库实现,会减少数据库的累赘,且会减少死锁的产生几率。此外,对于不会发生变化的只读数据,加锁只会减少额定不必要的累赘。在理论的实际中,对于并发很高的场景并不会应用乐观锁,因为当一个事务锁住了数据,那么其余事务都会产生阻塞,会导致大量的事务产生积压拖垮整个零碎。 第二种方法 乐观锁select version from goods WHERE id= 1001update goods set num = num - 1, version = version + 1 WHERE id= 1001 AND num > 0 AND version = @version(下面查到的version);这种形式采纳了版本号的形式,其实也就是CAS的原理。 假如此时version = 100, num = 1; 100个线程进入到了这里,同时他们select进去版本号都是version = 100。 ...

September 9, 2020 · 1 min · jiezi

关于面试:答面试官问如何设计短url服务

什么是短url短url, 顾名思义,就是将长网址缩短到一个很短的网址,用户拜访这个短网址能够重定向到本来的长网址(还原)。这样能够达到易于记忆、转换的目标,还有暗藏链接参数,利于短信推广的作用,罕用于有字数限度的短信、微博、二维码等场景。 谬误答案这个实现的思路真的是天花乱坠,此处总结几种谬误的实现形式来避坑。 1. 实现一个算法,能够间接把一百个字符左右的长网址缩短到10位以内,并能够原样还原,即可逆不可能的。为所有可能存在的长链接实现一一对应,自身是不可能的,会呈现碰撞,多个长链接对应一个短链接,所以不会可逆。 2. 实现算法将长地址转短地址,不实现逆运算,将短长对应关系存数据库中不可能的。没有扭转实质(长链接数量远多于长链接),只有长链接够多,必然会碰撞 3. 用一个hash算法,生成的短链接碰撞后,在短链接前面加1,2,3物理逻辑上可行,生产利用不可行。效率会不可控的升高,通过算法算进去短url之后,hash碰撞后生成多个xx1,xx2,xx3....xx20...的短url,长短对应数量不可控,查找效率会升高。 4. 随机生成一个短地址,去数据库查找是否用过,用过就再随机,直到随机到一个没用过的短地址,存数据库物理逻辑上可行,生产利用不可行。每次生成都有必要的全量查问操作,必定是不OK的。 5. 保护一个超级大的全量数据,事后生成超过理论生产应用的短url,接口调用间接颁发,同步批改短url应用状态。物理逻辑上可行,生产利用低可用。具体是在redis还是db里批量生成其实是截然不同的两种实现。 若是redis, 那么外面要放入全量的短url么?否则怎么晓得这个短url到底是不是惟一的?如果全量,那对redis的可用性就要严格保障,为了高可用,就须要多节点同步维持全量数据,这个过程要做好不是那么的容易; 若是db, 那么就要有大量的并发锁定,意味着大量读写,这个对数据库也是个考验。 正确答案建设一个发号器,每次有一个新的长URL进来,咱们就减少一,并且将新的数值返回.第一个来的url返回"www.x.cn/0",第二个返回"www.x.cn/1". 细节问题短url的还原跳转用301还是302?301是永恒重定向,302是长期重定向。 短地址一经生成就不会变动,所以用301是合乎http语义的。同时浏览器会对301申请保留一个比拟长期的缓存,这样就加重对服务器的压力;而且301对于网址的SEO有肯定的晋升。然而很多状况下咱们须要对接口点击或者用户行为进行一些业务监控解决的时候,301显著就不适合了(浏览器间接依照缓存数据跳转了), 所以很多业务场景下还是采纳302比拟适合。 字符超长问题即便到了10亿(Billion)转换而成的62进制也无非是6位字符,所以长度根本不在思考范畴内,这个范畴足够应用了。 对应关系如何存储?这个对应数据必定是要落盘的,不能每次零碎重启就从新排号,所以能够采纳mysql等数据库来存储.而且如果数据量小且qps低,间接应用数据库的自增主键就能够实现. 如何保障长短链接一一对应?依照下面的发号器策略,是不能保障长短链接的一一对应的,你间断用同一个URL申请两次,后果值都是不一样的. 为了实现长短链接一一对应,咱们须要付出很大的空间代价,尤其是为了疾速响应,咱们能够须要在内存中做一层缓存,这样子太节约了. 然而能够实现一些变种的,来实现局部的一一对应, 比方将最近/最热门的对应关系存储在K-V数据库中,这样子能够节俭空间的同时,放慢响应速度. 短URL的存储咱们返回的短URL个别是将数字转换成62进制,这样子能够更加无效的缩短URL长度,那么62进制的数字对计算机来说只是字符串,怎么存储呢?间接存储字符串对等值查找好找,对范畴查找等太不敌对了. 其实能够间接存储10进制的数字,这样不仅占用空间少,对查找的反对较好,同时还能够更加不便的转换到更多/更少的进制来进一步缩短URL. 短码平安问题依照算法从0-61都是1位字符,而后2位、3位...这样的话很容易被人发现法则并进行攻打,当然进攻伎俩很多,申请签名之类的平安验证伎俩不在本文探讨范畴内。 首先计数器能够从一个比拟大的随机两头值开始,比方从10000开始计数,他的62进制是 2Bi 3位的字符串; 而后采纳一些校验位算法(比方Luhn改良一下),计算出1位校验位拼接起来,4位短码,这样能够排除肯定的平安危险; 再加点平安料的话,能够在62进制的转换过程中把排序好的62个字母数字随机打乱,比方ABCD1234打乱成1BC43A2D, 转换的62进制也就更难hack了; 最初如果仍不释怀,还能够在某些地位(比方1,3,5)插入随机数,让人无奈看出法则来也能够达到良好的成果。 同一长网址短url是否应该雷同问题发号策略中,是不判断长地址是否已转过,所以造成后果就是一长对多短,有人说节约空间,建设一个长对短的map存储即可,然而用map存储自身就是节约大量空间,甚至是用大空间换小空间,这就要思考是否真有必要做一一对应,不能一对多; 最简略计划:建一个长对短的map,空间换空间, 更好的计划:用map存储"最近"生成的长对短关系,一小时过期机制实现LRU淘汰 长对短流程: 这个“最近”表中查看一下,看长地址有没有对应的短地址有就间接返回,并且将这个key-value对的过期工夫重置为一小时如果没有,就通过发号器生成一个短地址,并且将这个“最近”表中,过期工夫为1小时当一个地址被频繁应用,那么它会始终在这个key-value表中,总能返回当初生成那个短地址,不会呈现反复的问题。如果它应用并不频繁,那么长对短的key会过期,LRU机制主动就会淘汰掉它。 这样在空间和发号数量之间获得了一个均衡,此处也应该看具体的业务需要来,是否会存在一对多的状况。比方下单未领取,给用户发短信召回,短信内的短url外面存在用户昵称,订单号等个性化信息,即不须要减少这一逻辑环节了。 高并发如果间接存储在MySQL中,当并发申请增大,对数据库的压力太大,可能会造成瓶颈,这时候是能够有一些优化的. 缓存 下面保障长短链接一一对应中也提到过缓存,这里咱们是为了放慢程序处理速度. 能够将热门的长链接(须要对长链接进来的次数进行计数),最近的长链接(能够应用redis保留最近一个小时的)等等进行一个缓存,保留在内存中或者相似redis的内存数据库中,如果申请的长URL命中了缓存,那么间接获取对应的短URL进行返回,不须要再进行生成操作. 批量发号 每一次发号都须要拜访一次MySQL来获取以后的最大号码,并且在获取之后更新最大号码,这个压力是比拟大的. 咱们能够每次从数据库获取10000个号码,而后在内存中进行发放,当残余的号码有余1000时,从新向MySQL申请下10000个号码.在上一批号码发放完了之后,批量进行写入. 这样能够将对数据库继续的操作移到代码中进行,并且异步进行获取和写入操作,保障服务的继续高并发. 分布式下面设计的零碎是有单点的,那就是发号器是个单点,容易挂掉. 能够采纳分布式服务,分布式的话,如果每一个发号器进行发号之后都须要同步给其余发号器,那未必也太麻烦了. 换一种思路,能够有两个发号器,一个发单号,一个发双号,发号之后不再是递增1,而是递增2. 类比可得,咱们能够用1000个服务,别离发放0-999尾号的数字,每次发号之后递增1000.这样做很简略,服务相互之间根本都不必通信,做好本人的事件就好了. 转自https://www.kancloud.cn/marti...欢送关注哦

September 9, 2020 · 1 min · jiezi

关于面试:面试题锦1-|-你知道什么是BFC吗

从今天起,“小葵花妈妈课堂”啦!???? 大家都晓得,面试犹如考试,在考试之前,老师个别都会先给咱们理清常识脉络,整顿温习纲要,依照纲要精准学习,疾速达到应试状态。所以,一本精炼的温习纲要对面试尤为重要。本武林秘笈从本周开始,每周会更新3-5个知识点,尽量的精简与提炼常识脉络,极为适宜利用碎片工夫来学习。心愿你和我一起,每周提高一点点~???? 1. CSS选择器及其优先级选择器的优先级由高到低: !important内联款式(style='xxx')(1000)ID选择器(#example)(0100)类选择器(.example)/属性选择器([type="radio"])/伪类选择器(:hover)(0010)标签选择器(h1)/伪元素选择器(::before)(0001)通配符选择器(*)/关系选择器(+,>,~,' ',||)/否定伪类(:not())(0000)注:通配选择器(*)、组合选择器(+,>,~,' ',||)和否定伪类(:not())不会影响优先级(然而,:not()外部申明的选择器会影响优先级)。 优先级是由A、B、C、D的值来决定的,其中它们的值计算规定如下: 如果存在内联款式,那么A = 1,否则A = 0;B 的值等于 ID选择器 呈现的次数;C 的值等于 类选择器 和 属性选择器 和 伪类 呈现的总次数;D 的值等于 标签选择器 和 伪元素 呈现的总次数 。这么很形象,那么来个例子你就懂了: #nav-global > ul > li > a.nav-link套用下面的算法,顺次求出 A B C D 的值: 因为没有内联款式 ,所以 A = 0;ID选择器总共呈现了1次, B = 1;类选择器呈现了1次, 属性选择器呈现了0次,伪类选择器呈现0次,所以 C = (1 + 0 + 0) = 1;标签选择器呈现了3次, 伪元素呈现了0次,所以 D = (3 + 0) = 3; ...

August 31, 2020 · 2 min · jiezi

关于面试:3年PHPer的面试总结

根底局部1.HTTP中GET与POST的区别,留神最初一条GET在浏览器回退时是有害的,而POST会再次提交申请。GET产生的URL地址能够被Bookmark,而POST不能够。GET申请会被浏览器被动cache,而POST不会,除非手动设置。GET申请只能进行url编码,而POST反对多种编码方式。GET申请参数会被残缺保留在浏览器历史记录里,而POST中的参数不会被保留。GET申请在URL中传送的参数是有长度限度的,而POST没有。对参数的数据类型,GET只承受ASCII字符,而POST没有限度。GET比POST更不平安,因为参数间接裸露在URL上,所以不能用来传递敏感信息。GET参数通过URL传递,POST放在Request body中。GET产生一个TCP数据包,POST产生两个TCP数据包。 2.为什么Tcp连贯是三次,挥手是四次在Tcp连贯中,服务端的SYN和ACK向客户端发送是一次性发送的,而在断开连接的过程中,B端向A端发送的ACK和FIN是分两次发送的。因为在B端接管到A端的FIN后,B端可能还有数据要传输,所以先发送ACK,等B端解决完本人的事件后就能够发送FIN断开连接了。 3.Cookie存在哪如果设置了过期工夫,Cookie存在硬盘里没有设置过期工夫,Cookie存在内存里 4.COOKIE和SESSION的区别和关系COOKIE保留在客户端,而SESSION则保留在服务器端从安全性来讲,SESSION的安全性更高从保留内容的类型的角度来讲,COOKIE只保留字符串(及可能主动转换成字符串)从保留内容的大小来看,COOKIE保留的内容是无限的,比拟小,而SESSION基本上没有这个限度从性能的角度来讲,用SESSION的话,对服务器的压力会更大一些SEEION依赖于COOKIE,但如果禁用COOKIE,也能够通过url传递 PHP相干Session可不可以设置生效工夫,比方30分钟过期设置seesion.cookie_lifetime有30分钟,并设置session.gc_maxlifetime为30分钟本人为每一个Session值减少timestamp每次拜访之前, 判断工夫戳 PHP过程间通信的几种形式音讯队列信号量+共享内存信号管道socket php类的动态调用和实例化调用各自的利弊静态方法是类中的一个成员办法,属于整个类,即便不必创立任何对象也能够间接调用!静态方法效率上要比实例化高,静态方法的毛病是不主动销毁,而实例化的则能够做销毁。 类的数组形式调用ArrayAccess(数组式拜访)接口 用php写一个函数,获取一个文本文件最初n行内容,要求尽可能效率高,并能够跨平台应用。function tail($file, $num){ $fp = fopen($file,"r"); $pos = -2; $eof = ""; $head = false; //当总行数小于Num时,判断是否到第一行了 $lines = array(); while ($num > 0) { while($eof != PHP_EOL){ if (fseek($fp, $pos, SEEK_END) == 0) { //fseek胜利返回0,失败返回-1 $eof = fgetc($fp); $pos--; } else { //当达到第一行,行首时,设置$pos失败 fseek($fp, 0, SEEK_SET); $head = true; //达到文件头部,开关关上 break; } } array_unshift($lines, str_replace(PHP_EOL, '', fgets($fp))); if ($head) {//这一句,只能放上一句后,因为到文件头后,把第一行读取进去再跳出整个循环 break; } $eof = ""; $num--; } fclose($fp); return $lines; } $SERVER['SERVER_NAME']和$SERVER['HTTP_HOST']的区别相同点: 当满足以下三个条件时,两者会输入雷同信息。 ...

August 23, 2020 · 7 min · jiezi

关于面试:9个典型的开发者关系面试题

简介: 越来越多的科技公司正在从传统的企业销售思路转变为以开发者至上的思路来推广产品。因为开发者不喜爱这类销售形式,所以电话销售和演示将不起作用。 越来越多的科技公司正在从传统的企业销售思路转变为以开发者至上的思路来推广产品。因为开发者不喜爱这类销售形式,所以电话销售和演示将不起作用。 相同,平台须要采纳相似于消费者可能采纳手游或电商利用的形式。 然而,开发者也不太可能承受那些游戏和电商利用上的那些Facebook广告。 启动开发人员关系打算,能够推动开发者的应用并建设起更无效的关系,然而因为开发人员关系是一个簇新的角色,所需的技能和责任相比销售和工程等曾经成熟的角色来说更加含糊。 本文概述了招聘开发者关系经理时应留神的事项。无关开发人员关系的概述,能够先理解一下什么是开发者关系。 指标因为开发者关系对于任何与开发者社区互动的人来说都是一个无所不包的角色,所以在面试任何候选人之前,你应该列出这个角色的要害指标。一些开发者关系的角色侧重于社区参加和开发者宣传。 他们的次要指标是进步产品认知度,这要求他们在会议上发言,扩充本身影响力,并参加社交社区(如Twitter或Reddit)互动。 其余一些开发者关系的角色更专一于产品治理和开发者教训。他们的次要指标是平台的采纳和应用,这要求他们通过迭代的形式实现用户疏导、文档与公共的API/SDK。 无论表演那种角色,开发者关系经理都须要清晰地沟通,并深入浅出地把深奥的技术主题表达出来,以便开发者轻松的了解。很多时候,开发者关系是公司线上线下的形象代言人。 | 1. 通知我你见过最好的开发者体验是什么,为什么是最好的?一位优良的开发者关系经理领有基于平台和API构建的教训,他们分明的理解是什么造就了杰出的开发者体验,以及可能出错的中央。 对开发者关系团队来说,为喜爱的工具和产品提出强烈的意见并不常见。 | 2. 有什么北极星指标能够很好的来掂量开发者体验?一个有教训的开发者关系经理可能曾经看到了将指标调整为漏斗指标(如页面浏览量和注册量)而不思考产品参与度和留存率的结果。 开发者关系的北极星指标包含每周沉闷的token或第一次"hello world"的工夫。 | 3. 你最喜爱的开发者用户疏导是什么?为什么喜爱?一位优良的开发者关系经理有一双长于发现风行API产品和开发工具中的小惊喜,以及晓得增加它们的起因。 用户疏导(Onboarding)是任何一个API产品最重要的流程之一,因为很多时候,在API被集成之前,用户并没有收到任何价值的信息。向候选人介绍为什么某个产品的用户疏导是胜利的,以及你会对其进行哪些改良。 | 4. 创立开发者文档的最佳计划是什么?很多时候(但并不总是),开发者关系团队负责文档的继续更新。在这里,你正寻找在放弃以客户为核心的同时能够更自动化的执行文档的方法。 候选人是否相熟OpenAPI标准和Postman接口测试等工具? 候选人是更喜爱用Markdown这样的凋谢工具来编写文档,还是用Zendesk这样的客户反对工具来编写? 候选人如何解决GitHub README.md、API reference和官网上的开发者文档中可能存在的反复信息? 是否有思考以指标角色为核心,创立不同类型的文档? | 5. 你会在Meetup或会议上发言嘛?哪一次?是如何抉择话题的?加入会议和在会议上发言都是任何开发者关系经营策略的要害支柱。你须要的是一个不仅长于沟通,而且充满热情的帮忙开发者的人。演讲者的话题应该是乏味的,适宜听众的,并且与公司相干的。 | 6. 开发者平台正在产生什么乏味的新趋势?优良的开发者关系经理会及时理解与社区相干的新趋势和新闻。开发者关系经理应该相熟GraphQL等新技术和AWS Lambda等为开发者构建的全新平台。 通过这样,他们就能够对开发者社区进行培训并提供倡议。 | 7. 为什么API和SDK的版本治理很重要?如何对API进行版本治理?如果没有版本控制,任何更改都能够被视为重大更改,并毁坏了协同工作的初衷。 寻找那些关注开发者并领有同理心的候选人,即便这意味着要反对过期Java版本的旧版SDK。因为不是每个开发者都起因将其降级到最新的SDK和框架。 他们还应该相熟semvar(语义化版本标准)的益处,以及沟通非突破性变动与全面检修API的形式。 | 8. 如何解决API性能上的取舍?与消费类利用不同,API产品在解决任何性能时都须要认真布局。简直总是,最好的答案是永远不要引入任何重大更改,也不要删除一个字段。 例如,API响应有一个名为name的繁多JSON字段,你想把它拆成first_name、last_name和username。那么,正确的办法是在放弃旧的字段持续可用的同时增加新的字段。 在须要进行重大更改的状况下,例如修复安全漏洞或勾销整个产品。你须要跟进候选人是如何解决这些状况的。 这可能包含向拜访API的开发者发送个性化电子邮件,具体阐明他们应用的版本以及停用API的具体工夫等信息。 其余策略包含在非工作工夫(如周日下午1点)内短时间的敞开性能。 | 9. 您将如何划分开发者社区?有很多办法能够对开发者社区进行细分,用于营销、群体剖析和其余剖析。除了公司规模等典型的公司人口统计之外,还要关注以开发者为核心的这一个要害属性。 一个API开发者关系经理不仅要相熟常见的编程语言,还要相熟它们在业务中的应用状况。例如,Java和.NET在比拟传统的企业中很受欢迎,而Node.js则在React和单页面利用(Single Page App)社区中很受欢迎。 作者:Derric Gilling 编译:庄七

August 17, 2020 · 1 min · jiezi

关于面试:初面复盘2020815后端

先说一句:面试官上来强调本人不是学java的,次要探讨为主,可是我发现面试官问的问题一点都不像没学过java~共面了1小时40分钟1.java垃圾回收机制新生代/老年代 其它垃圾回收机制2.java面向对象个性继承封装多态3.设计模式 4.单例模式 5.map的底层实现 6.hash函数如何实现 7.哈希抵触的解决办法再哈希建设公共缓冲区 8.hashmap查问复杂度/升高复杂度办法 9.hashmap线程不平安 10.juc中的concurrentHashmap如何保障线程平安 11.罕用的汇合类型arraylistlinkedlist12.arrayList和linkedList区别 13.链表中如何使查问速度更快建索引?14.晓得哪些本地缓存?redis?lru? 15.计算机网络七层模型 16.浏览器每一个标签页都是一次tcp连贯吗 17.http和https的比拟 18.https加密算法是对称的还是非对称的? 19.TCP三次握手四次挥手 20.伪造第三次握手,如何保障? 21.syn攻打?还是什么攻打? 22.TIME_WAIT作用 23.多路复用、epoll办法的长处 存储连贯的是链表吗select poll epoll24.过程和线程 25.线程间通信 26.过程间通信 27.共享内存是在A过程中还是B过程?应该都不是28.线程间同步 29.sychronized和RetrantLock异同点 30.乐观锁和乐观锁,他们的效率 31.每次申请都是对锁的一个批改,两种策略效率如何 32.排序算法及各自的最好最坏复杂度及稳定性 33.归并排序和疾速排序的算法思维分治34.疾速排序的最坏状况,如何扭转 35.雷同的子问题能够用分治法,那不同的子问题? 36.最初一题算法题牛客网本题探讨链接小Q在进行一场竞技游戏,这场游戏的输赢要害就在于是否抢夺一条长度为L的河道,即能够看做是[0,L]的一条数轴。这款竞技游戏当中有n个能够提供视线的道具--真视守卫,第i个真视守卫可能笼罩[xi,yi]。当初小Q想晓得至多用几个真视守卫就能够笼罩整段河道。 输出形容:输出包含n+1行第一行包含两个正整数n和L(1<=n<=10^5,1<=L<=10^9)接下来的n行,每行两个正整数xi,yi(0<=xi<=yi<=10^9),示意第i个真视守卫笼罩的区间输入形容,一个示意起码须要的真视守卫数量,如果无解,输入-1。 样例:输出:4 63 62 40 24 7输入3 import java.util.Arrays;import java.util.Scanner;public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); int n = input.nextInt(); int L = input.nextInt(); int[][] nums = new int[n][2]; int ce = 0; while (ce < n) { nums[ce][0] = input.nextInt(); nums[ce][1] = input.nextInt(); ce++; } System.out.println(guidenum(nums, L)); } public static int guidenum(int[][] nums, int L) { int count = 0; Arrays.sort(nums, (a, b) -> a[0] - b[0]); int start = 0, end = 0; for (int i = 0; start < L; ) { for (; i < nums.length && nums[i][0] <= start; i++) end = Math.max(end, nums[i][1]); if (start == end) { return -1; } start = end; count++; } return count; }}

August 16, 2020 · 1 min · jiezi

关于面试:网易一面面经30分钟

网易一面面经(30分钟)自我介绍,介绍我的项目介绍Spring,以及Ioc,aopaop的实现,具体介绍动静代理汇合,hashmap,扩容机制synchronized在jvm的实现过程lock加锁的过程死锁,现场形容死锁的情况垃圾回收,可达性剖析mysql建表索引的建设,索引为什么会提高效率redis数据类型和应用场景redis在多线程操作时如何与mysql同步反诘

August 15, 2020 · 1 min · jiezi

关于面试:网易一面面经30分钟

网易一面面经(30分钟)自我介绍,介绍我的项目介绍Spring,以及Ioc,aopaop的实现,具体介绍动静代理汇合,hashmap,扩容机制synchronized在jvm的实现过程lock加锁的过程死锁,现场形容死锁的情况垃圾回收,可达性剖析mysql建表索引的建设,索引为什么会提高效率redis数据类型和应用场景redis在多线程操作时如何与mysql同步反诘

August 15, 2020 · 1 min · jiezi

关于面试:腾讯面经总结20200815面试前

简历我的项目相干;1.spring security2.json web token3.mybatis4.aop代理,动静代理,动态代理5.redis 1.索引,什么是B+树2.索引太多有什么问题,三个方面各三点3.redis有什么数据结构4.https是什么,工作原理5.响应状态码6.tcp三次握手、四次挥手7.tcp流量管制8.讲一下hashmap9.hash算法10.如果有个很大的10g文件,外面都是数字,你的内存只有2g,你怎么样读进来而后排序,最好具体到源码 1.java多线程和高并发2.线程池参数以及几个线程池的细分3.java提供了几个类加载器?别离是?怎么对类进行加载?4.hashCode的作用,重写须要留神什么https://www.cnblogs.com/honoka/p/4827721.html5.classnotfoundexception 晓得吗?遇到场景是什么?怎么解决的?6.NoSuchMethodException遇到过吗 1.TCP/IP有几层?那些?传输层有哪些协定?http是基于什么协定的?2.cookies和session的区别?3.session是怎么做辨别的?4.cookie是怎么传到前端的?服务器在响应头外面设置Set-Cookie字段5.物理层咱们罕用的协定有哪些?6.我的项目里有个数据安全的,aes和md5的区别?具体点aes是流明码体系,次要是做传输时的加密。md5次要是签名的时候用的,通过hash做的7.单点登录怎么实现的?8.https怎么实现的?SSL和TLS的区别?9.上海和深圳两个集群,他们https加密的公共密钥怎么同步?10.页面报错了,你怎么排查? 1.jvm构造分区以及调优(栈、堆、办法区、程序计数器,简略的-ea -Xmx2g -Xms2g -XX:MaxPermSize=1024m)2.线程池的各个参数以及值,用了什么队列,回绝策略(外围线程数 50,最大 100,ArrayBlockingQueue 默认抛弃)3.我的项目中有没用到微服务 4.mybatis和hibernate相比(轻量级,不须要反向生成,动静sql间接在接口上写注解sql语句,不便)5.为什么选ssm框架(支流,不便易用) 1.垃圾回收器CMS与G1 2.垃圾回收算法 3.堆外内存、IO与NIO 4.HTTP与HTTPs 5.对称加密算法与非对称加密算法 6.hashmap、hashtable、7.concurrentHashMap 8.线程平安、synchronized、volatile 9.疾速排序、工夫复杂度 10.sort外部实现 11.自旋锁 12.linux命令、内核态 1.Spring DI 是什么?如何实现?2.Spring AOP 是什么?实现原理?3.HashMap 底层实现?反对并发的 HashMap 有哪些?4.JVM 内存布局?5.synchronized 的底层实现?6.线程的创立形式?线程池的要害参数?7。介绍TCP的三次握手四次挥手?8.为什么会有TIME_WAIT和CLOSE_WAIT?9.介绍一下拥塞管制?10.过程和线程的区别?11.理解mysql的索引嘛?聚簇索引和非聚簇索引的区别?12.索引的构造?13.查问很慢,如何优化? 1.呈现OOM,如何剖析和解决?2.Web端实现实时通信的办法有哪些?3.Web端登陆的安全性如何实现?4.Linux中,如何查问零碎负载状况?CPU利用率如何计算?5.【编程】151. 翻转字符串里的单词 - 力扣(LeetCode) 1.操作系统 内存局部(虚拟地址怎么找到物理地址) 2.swap分区 3.为什么用虚拟地址 4.linux怎么查看内存状况 5.过程的堆栈外面放的什么6.快排  归并排序 7.口述算法 最长回文子串 8.三次握手 9.syn攻打 10.多态 11.hashmap  hashtable 12.线程状态(blocked   waiting  timed_waiting) 13.jvm内存调配 14.==  equals  hashcode 15.数据库隔离级别 16.脏读  幻读 1.对并发的了解2.synchronized 和  lock 3.juc你意识的工具类4.爬楼梯问题5.mysql连贯对象问题 6.长事务 7.mvcc 1.说对spring mvc 和spring cloud的了解2.说一下tcp 和 udp3.tcp的time wait 和 close wait4.说一下拥塞管制5.怎么管制滑动窗口的大小6.如果服务器端已进入close状态,客户端还处于time wait 状态,占用着端口,怎么解决7.查看tcp连接数的命令 8.linux你晓得哪些命令9.linux 中 ‘|’的作用是什么?10.以后零碎的性能遇到了瓶颈,如何去定位问题11.内存泄露怎么定位12.说说你调优jvm的方向13.说说jvm gc的特点,你的了解 ...

August 11, 2020 · 1 min · jiezi

关于面试:面试官你们项目中是怎么做防重复提交的

面试经验记得刚毕业的时候,有一次去加入面试。 上来面试官问我:“你们我的项目中是怎么做防反复提交的?” 一开始听到这个问题是蒙圈的,支支吾吾半天没答复进去。 而后面试官间接来一道算法题,脍炙人口地面试失败。 多年过来,尽管很少接触到控台利用,然而近期对于避免反复提交却有了一点本人的心得。 在这里分享给大家,心愿你工作或者面试中遇到相似的问题时,对你有所帮忙。 本文将从以下几个方面开展: (1)反复提交产生的起因 (2)什么是幂等性 (3)针对反复提交,前后端的解决方案 (4)如果实现一个防反复提交工具 产生起因因为反复点击或者网络重发 eg: 点击提交按钮两次; 点击刷新按钮; 应用浏览器后退按钮反复之前的操作,导致反复提交表单; 应用浏览器历史记录反复提交表单; 浏览器反复的HTTP申请; nginx重发等状况; 分布式RPC的try重发等; 次要有 2 个局部: (1)前端用户操作 (2)网络申请可能存在重试 当然也不排除一些用户的歹意操作。 java 表单防止反复提交问题就是同一份信息,反复的提交给服务器。 场景点击F5刷新页面: 当用户点击submit将曾经写好的表单数据提交到服务器时,能够在浏览器的url看到地址和参数的变动,但因为网速等问题,用户以后页面并未刷新,或者点击刷新页面,造成表单反复提交。反复点击提交按钮: 因为网络问题,未能及时跳转显示内容,局部用户可能会出于心急反复提交提交按钮,造成屡次提交内容到服务器。后退后退操作 :有些用户在进行某些工作操作时,可能出于须要或者某种状况,进行后退操作,浏览方才填入的信息,在进行后退和后退的操作可能也会造成表单数据反复提交到服务器。应用浏览器历史记录反复拜访: 某些用户可能会出于好奇,利用浏览器的历史记录性能反复拜访提交页面,同样会造成表单反复提交问题。解决思路前端计划一:禁用按钮提交设置标记位,提交之后禁止按钮。像一些短信验证码的按钮个别都会加一个前端的按钮禁用,毕竟发短信是须要钞票滴~ ps: 以前写前端就用过这种形式。 长处简略。根本能够避免反复点击提交按钮造成的反复提交问题。 缺点后退后退操作,或者F5刷新页面等问题并不能失去解决。 最重要的一点,前端的代码只能避免不懂js的用户,如果碰到懂得js的编程人员,那js办法就没用了。 计划二:设置HTTP报头设置HTTP报头,管制表单缓存,使得所管制的表单不缓存信息,这样用户就无奈通过反复点击按钮去反复提交表单。 <meta http-equiv="Cache-Control" content="no-cache, must-revalidate">然而这样做也有局限性,用户在提交页面点击刷新也会造成表单的反复提交。 计划三:通过 PRG 设计模式用来避免F5刷新反复提交表单。 PRG模式通过响应页面Header返回HTTP状态码进行页面跳转代替响应页面跳转过程。 具体过程如下: 客户端用POST办法申请服务器端数据变更,服务器对客户端发来的申请进行解决重定向到另一个后果页面上,客户端所有对页面的显示申请都用get办法告知服务器端,这样做,后退再后退或刷新的行为都收回的是get申请,不会对server产生任何数据更改的影响。这种办法实现起来绝对比较简单,但此办法也不能避免所有状况。例如用户屡次点击提交按钮;歹意用户避开客户端预防屡次提交伎俩,进行反复提交申请; 上面谈一谈后端的避免反复提交。 后端幂等性如果是注册或存入数据库的操作,能够通过在数据库中字段设立惟一标识来解决,这样在进行数据库插入操作时,因为每次插入的数据都雷同,数据库会回绝写入。 这样也防止了向数据库中写入垃圾数据的状况,同时也解决了表单反复提交问题。 然而这种办法在业务逻辑上感觉是说不过去的,原本该有的逻辑,却因为数据库该有的设计暗藏了。 而且这种办法也有肯定的性能局限性,只实用于某系特定的插入操作。 实现形式这种操作,都须要有一个惟一标识。数据库中做惟一索引束缚,反复插入间接报错。 毛病有很大的约束性。 个别都是最初的一道防线,当申请走到数据库层的时候,个别曾经耗费了较多的资源。 session 办法Java 应用Token令牌避免表单反复提交的步骤: 在服务器端生成一个惟一的随机标识号,专业术语称为Token(令牌),同时在以后用户的Session域中保留这个Token。将Token发送到客户端的Form表单中,在Form表单中应用暗藏域来存储这个Token,表单提交的时候连同这个Token一起提交到服务器端。在服务器端判断客户端提交上来的Token与服务器端生成的Token是否统一,如果不统一,那就是反复提交了,此时服务器端就能够不解决反复提交的表单。如果雷同则解决表单提交,解决完后革除以后用户的Session域中存储的标识号。上面的场景将回绝解决用户提交的表单申请 存储Session域中的Token(令牌)与表单提交的Token(令牌)不同。以后用户的Session中不存在Token(令牌)。这里的 session 依照单机和分布式,能够应用 redis/mysql 等解决分布式的问题。 这种办法算是比拟经典的解决方案,然而须要前后端的配合。 ...

August 5, 2020 · 5 min · jiezi

关于面试:技术支持岗面试问题精选干货合集

交换机与路由器的区别1.路由器能拨号,交换机不能 2.无线路由器能使无线设施WIFI上网,交换机不行 3.形状上:从形状上咱们辨别两者,交换机通常端口比拟多看起来比拟轻便,而路由器的端口就少得多体积也小得多。 4.工作档次不同: 最后的交换机工作在OSI开放式系统互联模型的数据链路层,也就是第二层,而路由器则工作在OSI模型的网络层,就是第三层。也就是因为这一点所以交换机的原理比较简单,个别都是采纳硬件电路实现数据帧的转发,而路由器工作在网络层,肩负着网络互联的重任,要实现更加简单的协定,具备更加智能的转发决策性能,个别都会在在路由器中跑操作系统,实现简单的路由算法,更偏差于软件实现其性能 5.数据的转发对象不同:交换机是依据MAC地址转发数据帧,而路由器则是依据IP地址来转发IP数据报/分组。数据帧是在IP数据包/分组的根底上封装了帧头(源MAC和目标MAC等)和帧尾(CRC校验码)。IP地址决定最终数据包要到达某一台主机,而MAC地址则是决定下一跳将要交互给哪一台设施(个别是路由器或主机)。而且,IP地址是软件实现的,能够形容主机所在的网络,MAC地址是硬件实现的,每一个网卡在出厂的时候都会将全世界惟一的MAC地址固化在网卡的ROM中,所以MAC地址是不能被批改的,然而IP地址是能够被网络管理人员配置批改的。 6.负载不同:交换机之间只能有一条通路,使得信息集中在一条通信链路上,不能进行动态分配,以均衡负载。而路由器的路由协定算法能够防止这一点,路由协定算法岂但能产生多条路由,而且能为不同的网络应用抉择各自不同的最佳路由 7.在回路上:依据交换机地址学习和站表建设算法,交换机之间不容许存在回路。一旦存在回路,必须启动生成树算法,阻塞掉产生回路的端口。而路由器的路由协定没有这个问题,路由器之间能够有多条通路来均衡负载,进步可靠性。 8.网络互连上:目前交换机次要实现雷同或类似物理介质和链路协定的网络互连,而不会用来在物理介质和链路层协定相差甚元的网络之间进行互连。而路由器则不同,它次要用于不同网络之间互连,能连贯不同物理介质、链路层协定和网络层协定的网络。路由器在性能上尽管占据了劣势,但价格昂贵,报文转发速度低。 9.”分工“不同:交换机次要是用于组建局域网,而路由器则是负责让主机连贯外网。多台主机能够通过网线连贯到交换机,这时就组建好了局域网,就能够将数据发送给局域网中的其余主机,像咱们应用的飞秋就是通过交换机把数据转发给其余主机的,当然像极域电子教室这样的播送软件是利用播送技术让所有的主机都收到数据的。然而,通过交换机组建的局域网是不能拜访外网的(即是Internet),这时须要路由器来为咱们”关上里面精彩世界的大门“,局域网的所有主机应用的都是私网的IP,所以必须通过路由器转化为公网的IP之后能力拜访外网。 10.抵触域和播送域:交换机宰割抵触域,然而不宰割播送域,而路由器宰割播送域。由交换机连贯的网段仍属于同一个播送域,播送数据包会在交换机连贯的所有网段上流传,在这种状况下会导致播送风暴和安全漏洞问题。   而连贯在路由器上的网段会被调配不同的播送域,路由器不会转发播送数据。须要阐明的是单播的数据包在局域网中会被交换机惟一地送往指标主机,其余主机不会接管到数据,这是区别于原始的集线器的,数据的达到工夫由交换机的转发速率决定,替换机会转发播送数据给局域网中的所有主机。 11.性能不同:路由器个别有防火墙的性能,可能对一些网络数据包选择性过滤。当初的一些路由器都具备交换机的性能,一些交换机具备路由器的性能,被称为3层交换机,宽泛应用。相比较而言,路由器的性能较交换机要弱小,然而速度也较慢,价格昂贵,三层交换机既有交换机的线性转发报文的能力,又有路由器的良好的路由性能因而失去宽泛的应用。 三层交换机与两层交换机的区别1.工作层级不同:二层交换机工作在数据链路层,三层交换机工作在网络层,三层交换机不仅实现了数据包的高速转发,还能够依据不同网络情况达到最优网络性能。 2.原理不同:二层交换机的原理是当交换机从某个端口收到一个数据包,它会先读取包中的源MAC地址,再去读取包中的目标MAC地址,并在地址表中查找对应的端口。三层交换机的原理比较简单,就是一次路由屡次替换,也就是第一次进行源到目标的路由,三层替换机会将此数据转到二层,那么下次无论是目标到源还是源到目标都能够进行疾速替换。 3、性能不同:二层交换机基于MAC地址拜访,只做数据的转发,并且不能配置IP地址,而三层交换机将二层替换技术和三层转发性能联合在一起,就是说三层交换机在二层交换机的根底上减少了路由性能,可配置不同vlan(虚构局域网)的IP地址,vlan之间可通过三层路由实现不同vlan之间通信。 4、利用不同:二层交换机次要用于网络接入层和汇聚层,而三层交换机次要用于网络核心层,然而也存在少部分三层交换机用于汇聚层的景象。 5、反对的协定不同:二层交换机反对物理层和数据链路层协定,比方以太网交换机、二层交换机,这集线器HUB的性能差不多,而三层交换机反对物理层、数据链路层及网络层协定。 三层交换机与路由器的区别1)次要性能不同:尽管三层交换机与路由器都具备路由性能,但咱们不能因而而把它们等同起来,正如当初许多网络设备同时具备多种传统网络设备性能一样,就如当初有许多宽带路由器不仅具备路由性能,还提供了交换机端口、硬件防火墙性能,但不能把它与交换机或者防火墙等同起来一样。但这些路由器的次要性能还是路由性能,其它性能只不过是其附加性能,其目标是使设施实用面更广、使其更加实用。三层交换机也一样,它仍是交换机产品,只不过它是有了一些根本的路由性能的交换机,它的次要性能仍是数据交换。也就是说它同时具备了数据交换和路由转发两种性能,但其次要性能还是数据交换;而路由器仅具备路由转发这一种次要性能。 2)次要实用的环境不一样:三层交换机的路由性能通常比较简单,它所面对的次要是简略的局域网连贯。路由门路远没有路由器那么简单。它用在局域网中的主要用途还是提供疾速数据交换性能,满足局域网数据交换频繁的利用特点。 而路由器则不同,它的设计初哀就是为了满足不同类型的网络连接,尽管也实用于局域网之间的连贯,但它的路由性能更多的体现在不同类型网络之间的互联上,如局域网与广域网之间的连贯、不同协定的网络之间的连贯等,所以路由器次要是用于不同类型的网络之间。最次要的性能就是路由转发,解决好各种简单路由门路网络的连贯就是它的最终目标,所以路由器的路由性能通常十分弱小,不仅实用于同种协定的局域网间,更实用于不同协定的局域网与广域网间。它的劣势在于抉择最佳路由、负荷分担、链路备份以及和其余网络进行路由信息的替换等等性能。 3)性能体现不一样:从技术上讲,路由器和三层交换机在数据包替换操作上存在着显著区别。路由器是由基于微处理器的软件路由引擎执行数据包替换,而三层交换机通过硬件执行数据包替换。三层交换机在对第一个数据流进行路由后,它将会产生一个MAC地址与IP地址的映射表,当同样的数据流再次通过时,将依据此表间接从二层通过而不是再次路由,从而打消了路由器进行路由抉择而造成网络的提早,进步了数据包转发的效率。 还有,三层交换机的路由查找是针对数据流的,它利用缓存技术,很容易利用ASIC技术来实现,能够大大节约老本,并实现疾速转发。而路由器的转发采纳最长匹配的形式,实现简单,个别应用软件来实现,转发效率较低。 我认为,在局域网中进行多子网连贯,最好还选用三层交换机,特地是在不同子网数据交换频繁的环境中。一方面能够确保子网间的通信性能需求,另一方面省去了另外购买路由器的费用。如果子网间的通信不是很频繁,采纳路由器没有问题。 目前市面上领有主机与显示器相连的接口电脑主机连贯显示器的罕用接口有传统模仿VGA、数字高清DVI还有新一代数字高清HDMI接口,S视频端子接口。DisplayPort(DP)也是一种高清数字显示接口标准,能够连贯电脑和显示器,也能够连贯电脑和家庭影院. 15针 D-Sub接口就是VGA。VGA接口就是显卡上输入模拟信号的接口,VGA(Video Graphics Array)接口,也叫D-Sub接口 显示器连接线:常见的数据电缆类型有:HDMI连接线、VGA连接线、DVI连接线三大类。 另外还有近年来开始风行的 Display Port(DP)和Mini Display Port连接线,以及最新的Thunderbolt(次要用于Apple 2010年当前的Mac产品线)。 电脑网络显示×有什么解决排除办法?1.首先确认是否宽带欠费,具体能够拨打宽带服务商电话或者登录网上营业厅查问 2.接着查看网络接口,网络线路,如果有可能是网线出了问题,这时候重点放在网络线路的查看上。 3.接着查看路由器的电源是否插好,开关是否关上。查看光猫是否失常运行,个别光猫闪红灯阐明光纤有问题,就得分割运营商解决。还能够应用手机连贯局域网看是否上网,做一个排查。 4.查看电脑ip设置问题。如果网络线路没有问题,不能上网的问题多半出在电脑自身,须要检查一下电脑的ip设置,大部分电脑都是主动获取IP地址,如果人为设置了特定IP,在公网环境下可能导致无奈上网,能够在查看ip地址设置是否符合要求。当然如果电脑通过特定IP地址上网,你则须要查看IP是否被篡改。 5.查看网卡驱动问题。如果电脑右下角的网络图标显示黄色感叹号,可能是网卡驱动问题。能够尝试重启网卡驱动,或者从新装驱动来解决。 6.查看网卡是否被禁用。很多人在操作过程中不小心禁用了网卡,天然无奈上网。关上电脑的“网络与共享核心”,点击“更改适配器”进入“网络连接”,看上网图标是否被禁用,如果禁用,点击“启用”即可 7.可能是DNS解析问题,如果DNS服务器出错,则无奈进行域名解释,就不能上网。这种状况,有时候是网络服务接入商即ISP的问题,可打电话征询ISP;有时候则是路由器或网卡的问题,无奈与ISP的DNS服务连贯。方法就是从新设置路由器,还能够尝试用指定的DNS服务器地址。 8.病毒导致网络无奈连贯。这种状况不多,然而也不能排除,能够用杀毒软件进行全盘查杀,对电脑进行体检,个别能够解决。 电脑不能上网,有时候问题真的非常简单,略微检查一下就可能完满解决,多入手多思考很重要。 TCP与UDP区别总结:1、TCP面向连贯(如打电话要先拨号建设连贯);UDP是无连贯的,即发送数据之前不须要建设连贯 2、TCP提供牢靠的服务。也就是说,通过TCP连贯传送的数据,无差错,不失落,不反复,且按序达到;UDP尽最大致力交付,它不保障牢靠交付 Tcp通过校验和,重传管制,序号标识,滑动窗口、确认应答实现牢靠传输。如丢包时的重发管制,还能够对秩序乱掉的分包进行顺序控制。 3、UDP具备较好的实时性,工作效率比TCP高,实用于对高速传输和实时性有较高的通信或播送通信。 4.每一条TCP连贯只能是点到点的; UDP反对一对一,一对多,多对一和多对多的交互通信 5、TCP对系统资源要求较多,UDP对系统资源要求较少 利用场景抉择:对实时性要求高和高速传输的场合下应用UDP,在可靠性要求低,谋求效率的状况下应用UDP。须要传输大量数据且对可靠性要求高的状况下应用TCP。 云计算:直观上:云计算是一种按使用量免费的模式,如同水电个别,将计算能力作为免费模式 技术上:  与计算是分布式计算能力的一种,是透过宏大的计算解决网络分拆计算工作,计算后处理后果返回给用户,这个网络被成为云 云计算模式:1. SaaS:软件即服务——用户向互联网订购软件服务,而不必本人买软件,如Google Docs,Google App 2. PaaS:平台即服务——把开发环境作为服务,如Google App Engine,百度轻利用 3. IaaS: 基础设施即服务——即提供存储,虚拟化服务器服务,如AWS,淘宝云 电脑最小零碎:主板、内存、CPU、显示器,电源

August 3, 2020 · 1 min · jiezi

关于面试:这些手写代码会了吗少年

观感度:???????????????????? 口味:蟹黄豆腐 烹饪工夫:5min 本文已收录在前端食堂同名仓库Github github.com/Geekhyt,欢迎光临食堂,如果感觉酒菜还算可口,赏个 Star 对食堂老板来说是莫大的激励。从略带银丝的头发和干净利落的步调我察觉到,背后坐着的这个面试官有点深不可测。我像平常一样,筹备花 3 分钟的工夫给面试官来一套昨天晚上精心筹备的自我介绍。我自信且得意的诉说着对过往我的项目所付出的心血,所做的优化获得了怎么的成绩,为公司进步了多少的支出。。。 显然,面试官对我说的数字很感兴趣,嘴角微微上扬,通过了一番细节的探讨和技术的对线后。面试官拿出了一张纸。 手写代码。 重视根底的面试官是靠谱的,为了驯服他,我一边解说着实现原理一边写出了代码。 手写 callcall 和 apply 的区别:call 办法接管的是一个参数列表,apply 办法接管的是一个蕴含多个参数的数组。 1.context 存在就应用 context,否则是 window2.应用 Object(context) 将 context 转换成对象,并通过 context.fn 将 this 指向 context3.循环参数,留神从 1 开始,第 0 个是上下文,前面才是咱们须要的参数4.将参数字符串 push 进 args5.字符串和数组拼接时,数组会调用 toString 办法,这样能够实现将参数一个个传入,并通过 eval 执行6.拿到后果返回前,删除掉 fnFunction.prototype.call = function(context) { context = context ? Object(context) : window; context.fn = this; let args = []; for (let i = 1; i < arguments.length; i++) { args.push('arguments['+ i +']'); } let res = eval('context.fn('+ args +')'); delete context.fn; return res;}手写 apply1.apply 无需循环参数列表,传入的 args 就是数组2.然而 args 是可选参数,如果不传入的话,间接执行Function.prototype.apply = function(context, args) { context = context ? Object(context) : window; context.fn = this; if (!args) { return context.fn(); } let res = eval('context.fn('+ args +')'); delete context.fn; return res;}手写 bind1.bind 的参数能够在绑定和调用的时候分两次传入2.bindArgs 是绑定时除了第一个参数以外传入的参数,args 是调用时候传入的参数,将二者拼接后一起传入3.如果应用 new 运算符结构绑定函数,则会扭转 this 指向,this 指向以后的实例4.通过 Fn 链接原型,这样 fBound 就能够通过原型链拜访父类 Fn 的属性Function.prototype.bind = function(context) { let that = this; let bindArgs = Array.prototype.slice.call(arguments, 1); function Fn () {}; function fBound(params) { let args = Array.prototype.slice.call(arguments) ; return that.apply(this instanceof fBound ? this : context, bindArgs.concat(args)); } Fn.prototype = this.prototype; fBound.prototype = new Fn(); return fBound;}手写 new1.Constructor 就是 new 时传入的第一个参数,残余的 arguments 是其余的参数2.应用obj.__proto__ = Constructor.prototype 继承原型上的办法3.将残余的 arguments 传给 Contructor ,绑定 this 指向为 obj,并执行4.如果构造函数返回的是援用类型,间接返回该援用类型,否则返回 objconst myNew = function() { let Constructor = Array.prototype.shift.call(arguments); let obj = {}; obj.__proto__ = Constructor.prototype; let res = Constructor.apply(obj, arguments); return res instanceof Object ? res : obj;}手写 instanceOf1.在 left 的原型链中层层查找,是否有原型等于 prototype2.确定边界条件,如果 left === null,即找到头没找到返回 false,right === left,即找到返回 true3.left = left.__proto__,不停的向上查找const myInstanceof = function(left, right) { right = right.prototype; left = left.__proto__; while (true) { if (left === null) { return false; } if (right === left) { return true; } left = left.__proto__; }}手写 Object.create新建一个空的构造函数 F ,而后让 F.prototype 指向 obj,最初返回 F 的实例const myCreate = function (obj) { function F() {}; F.prototype = obj; return new F();} ...

August 3, 2020 · 2 min · jiezi

关于面试:又是面试题对合并有序序列

题图无关,因为想到鹅厂,就想到企鹅,而后就想到打企鹅(非洲版),而后就裸露年龄了[doge] - 鹅厂 -在边远的2009年,那时候“呵呵”还没有奇怪的意思,我笑呵呵地去加入了鹅厂的实习招聘。 面试被安顿在面试官下榻酒店的房间里,校门口的**王朝大酒店,可能一早晨能顶我一个月生活费那种。 过程聊得应该还能够,不过大部分细节都忘了,只记得最初那道代码题,一张纸,一支笔。 题面很简略:写一个 C 函数,合并两个有序数组。 - “最好能通用一点”,面试官补充说。 - “能够用 C++ 模板吗?” - “最好还是用 C 。” 好多年当前,当我开始面试他人了,发现这道题的确很好用。 - 解 -学过归并排序的同学应该都会感觉这个题目并不难,只不过是其中的一次归并环节。 其基本思路是,用两个指针,别离从数组的第一个元素开始,顺次比拟,每次找到最小的元素存入新数组,而后将指针挪动到下一位。 须要留神的是当一个数组被取完当前,还得解决另一个数组的残余元素。 而所谓“通用”,是指数组的元素能够是任意类型,因而须要把数组元素的大小、用于比拟的函数也作为参数传进去。 大略就是要实现这样的一个函数: typedef int cmpfunc(void *x, void *y);void* merge(void *A, int m, void *B, int n, int size, cmpfunc f);其中 m、n 别离示意 A、B 这两个数组的长度,size 示意数组元素的大小。 具体实现的 C 代码比拟琐碎,就不在这里贴出来了,感兴趣的同学能够本人试着写一下。 - WHY -我在上一家公司,通常用这道题当口试的压轴题,但不限度语言,以及去掉了对“通用”的要求。 为什么选它呢? 首先,它很容易了解,不会产生歧义,不须要额定解释。 其次,在纸面上编码(至多是脱离IDE),程序员在编码前得想分明;涂改较多也阐明一些问题。 最重要的是,它有很好的区分度,因为真的有很多程序猿没认真学过归并排序。 但至多每个人都能想到将两个数组合并,而后进行排序。 有些特地间接的小伙伴,就用了 PHP 自带的 sort 函数,起初咱们不得不加个阐明:“防止应用库函数”。 至于排序算法,有人写冒泡,也有人写快排;快排的实现,又能够考查是不是在数组里做原地划分(大部分是拆到两个数组里再合并)。 ...

August 1, 2020 · 2 min · jiezi

关于面试:又是面试题对合并有序序列

题图无关,因为想到鹅厂,就想到企鹅,而后就想到打企鹅(非洲版),而后就裸露年龄了[doge] - 鹅厂 -在边远的2009年,那时候“呵呵”还没有奇怪的意思,我笑呵呵地去加入了鹅厂的实习招聘。 面试被安顿在面试官下榻酒店的房间里,校门口的**王朝大酒店,可能一早晨能顶我一个月生活费那种。 过程聊得应该还能够,不过大部分细节都忘了,只记得最初那道代码题,一张纸,一支笔。 题面很简略:写一个 C 函数,合并两个有序数组。 - “最好能通用一点”,面试官补充说。 - “能够用 C++ 模板吗?” - “最好还是用 C 。” 好多年当前,当我开始面试他人了,发现这道题的确很好用。 - 解 -学过归并排序的同学应该都会感觉这个题目并不难,只不过是其中的一次归并环节。 其基本思路是,用两个指针,别离从数组的第一个元素开始,顺次比拟,每次找到最小的元素存入新数组,而后将指针挪动到下一位。 须要留神的是当一个数组被取完当前,还得解决另一个数组的残余元素。 而所谓“通用”,是指数组的元素能够是任意类型,因而须要把数组元素的大小、用于比拟的函数也作为参数传进去。 大略就是要实现这样的一个函数: typedef int cmpfunc(void *x, void *y);void* merge(void *A, int m, void *B, int n, int size, cmpfunc f);其中 m、n 别离示意 A、B 这两个数组的长度,size 示意数组元素的大小。 具体实现的 C 代码比拟琐碎,就不在这里贴出来了,感兴趣的同学能够本人试着写一下。 - WHY -我在上一家公司,通常用这道题当口试的压轴题,但不限度语言,以及去掉了对“通用”的要求。 为什么选它呢? 首先,它很容易了解,不会产生歧义,不须要额定解释。 其次,在纸面上编码(至多是脱离IDE),程序员在编码前得想分明;涂改较多也阐明一些问题。 最重要的是,它有很好的区分度,因为真的有很多程序猿没认真学过归并排序。 但至多每个人都能想到将两个数组合并,而后进行排序。 有些特地间接的小伙伴,就用了 PHP 自带的 sort 函数,起初咱们不得不加个阐明:“防止应用库函数”。 至于排序算法,有人写冒泡,也有人写快排;快排的实现,又能够考查是不是在数组里做原地划分(大部分是拆到两个数组里再合并)。 ...

August 1, 2020 · 2 min · jiezi

关于面试:Google的面试题长啥样看完被吊打

本文翻译自 Google 工程师/面试官 Alex Golec 的文章:Google Interview Questions Deconstructed: The Knight’s Dialer;起源:实验楼,翻译:实验楼扫地阿姨,原文:https://medium.com/@alexgolec... 作为一名Google的工程师和面试官,明天是我第二次发文分享科技公司面试倡议了。这里先申明:本文仅代表我集体的察看、意见和倡议。请勿当作来自Google或Alphabet的官网倡议或申明。 上面这个问题,是我面试生涯中第一个问题;也是第一个被透露进去,以及第一个被禁掉的问题。我喜爱这个问题,因为它有以下长处: 问题很容易表述分明,也容易了解。这个问题有多个解。每个解都须要不同水平的算法和数据结构常识。而且,还须要一点点远见。每个解都能够简略几行代码实现,非常适合有工夫限度的面试。如果你是学生,或者求职者,我心愿你通过本文可能理解到,面试问题个别会是怎么样的。如果你也是面试官,我很乐意分享本人在面试中的格调和想法,如何更好地传播信息、征求意见。 留神,我将应用Python写代码;我喜爱Python因为它易学,简洁,而且有海量的规范库。我遇到的很多面试者也很喜爱,只管咱们推广“不限定语言”的政策,我面试90%的人都用Python。而且,我用的Python 3因为,托付,这都2018年了。 问题把你的手机拨号页设想成一个棋盘。棋子走只能走“L”形态,横着两步,竖着一步;或者竖着两步,横着一步。 当初,假如你拨号只能像棋子一样走“L”形态。每走完一个“L”形拨一次号,起始地位也算拨号一次。问题:从某点开始,在N步内,你能够拨到多少不同的数字? 探讨每次面试,我根本都会分成两个局部:首先咱们找出算法计划,而后让面试者在代码中实现。我说“咱们找出算法计划”,因为这个过程我不是缄默的独裁者。在这样低压下,设计并实现一种算法,45分钟工夫并不算短缺。 我通常会让面试者主导探讨,让他们去产生想法,我嘛,就在旁边,时不时地透露一点点“天机”。面试者们能力越强,我须要透露的“天机”就越少;然而目前为止,我还没遇到一点都不须要我提醒的面试者。 有一点我想强调一下,重要的很:作为面试官,我的职责可不是坐那看着大家失败搞砸。我想要给大家侧面的反馈,给大家机会去展示大家最善于的点。给他们提醒,就像是在说:呐,这一步路我给你铺上,但这只是为了让你展现给我,你在前面的路上能走的更远。 当听完面试官的问题,你应该做什么? 切记不要立即就去写代码,而是在黑板上试着一步一步去合成问题。合成问题可能帮忙你寻找到法则,特例等等,逐步在大脑中造成解决方案。比方,你当初从数字6开始走,能走2步,会有如下组合: 6–1–86–1–66–7–26–7–66–0–46–0–6一共有6种组合。你能够试着用铅笔在纸上画,置信我,有时候入手去解决问题会产生意想不到的事,比你盯着在脑袋里想更神奇。 怎么样?你脑海里有计划了吗? 第0阶:达到下一步应用这个问题面试,最让我诧异的是,太多人都卡在了计算从某个特定点跳出时,一共有多少种可能,即邻Neighbors。我的倡议是:当你不确定时,先写个占位符,而后申请面试官是否晚点实现这一部分。 这个问题的复杂性并不在Neighbors的计算;我在意的是你如何计算出总数。所有破费在计算Neighbors上的工夫其实都是节约。 我会承受“让咱们假如有一个函数能给出我Neighbors”。当然,我也可能会让你前面有工夫再去实现这一步,你只须要这样写,而后持续。 而且,如果一个问题的复杂性不在这里,你也能够问我能不能先略过,个别我都是容许的。我倒是不介意面试者不晓得问题的复杂性在哪里,尤其刚开始他们还没有全面理解问题的时候。 至于Neighbors函数,因为数字永远不变,你能够间接写一个Map而后返回合乎的值。 第1阶:递归聪慧的你可能留神到了,这个问题能够通过枚举出所有符合条件的数字,而后计算。这里能够应用递归产生这些值: 这个办法能够,而且是在面试中最广泛的办法。然而请留神,咱们产生了这么多数字却并没有应用他们,咱们计算完他们的个数后,就再也不去碰了。所以我倡议大家遇到这种状况,尽量去想一下看有没有更好的计划。 第2阶:数不数数怎么在不产生这些数字的状况下计算出个数?能够做到,但须要一点点机智。留神从特定点跳出N次可能拨到的数字个数,等于从它所有邻近的点跳出N-1次可能拨到的数字个数的总和。咱们能够表白为这样的递归关系: 如果你这样想,就会很直观了,跳一次时:6有3个neighbors(1,7和0),当跳0次时每个数字自身算一次,因而每次你只能拨到3个数字。 怎么会产生这样机智的想法?其实,如果你学了递归,并且在黑板上好好钻研,这一点就会变得不言而喻。这样你就能持续去解决这个问题,实际上就这一点就有多种实现办法,上面这个便是面试中最常见的: 就是这样,联合这个函数计算出neighbors 就能够了。这时候,你就能够捏捏肩膀劳动下了,因为到这里,你曾经刷掉很多人了。 接下来这个问题我常常问:这个计划的算法实践速度如何?在这个实现中,每次调用count_sequences()都会递归地调用count_sequences()至多2次,因为每个数字至多有2个neighbors。这样会导致runtime成指数增长。 对于跳1次到20次这样的次数还能够,然而到更大的数字,咱们就要碰壁。500次可能就须要整个宇宙的热量来实现运算。 第3阶:记忆那么,咱们能做的更好么?应用下面的办法,并不能。我喜爱这个问题,也是因为他能一层一层带出大家的智慧,找到更高效的办法。为了找到更好的办法,让咱们看下这个函数是怎么调用的,以count_sequences(6, 4)为例。留神这里用C作为函数名简化。 你可能留神到了,C(6, 2)运行了3次,每次都是同样的运算并返回同样的值。这里最要害的点在于这些反复的运算,每次你应用过他们的值之后,就没有必要再次计算。 怎么解决这个问题?记忆。咱们那些雷同的函数调用和后果,而不是让他们反复。这样,在前面咱们就能够间接给出之前的后果。实现办法如下: 第4阶:动静设计如果你再看看后面的递归关系,就会发现递归记忆的计划也有一点局限性: 留神跳N次的后果仅仅取决于跳N-1次后调用的后果。同时,缓存中蕴含着每个次数的所有后果。我之所以说这是个小局限,因为的确不会造成真的问题,当跳的次数增长时,缓存也只是线性增长。然而,毕竟,这还是不够高效。 怎么办?让咱们再来看一看计划和代码。留神,代码中是从最大的次数开始,而后间接递归到最小的次数: 如果你把整个的函数调用图设想成某种虚构的树,你就会发现咱们在执行深度优先策略。这并没有什么问题,然而它没有利用到浅依赖这个属性。 如何实现广度优先策略? 这里就是一种实现办法: ...

August 1, 2020 · 1 min · jiezi

关于面试:子网划分

计算机网络子网划分子网划分的计算:IP地址分为: 默认子网掩码A类地址:0结尾 255.0.0.0B类地址:10结尾 255.255.0.0C类地址:110结尾 255.255.255.0D类地址:1110结尾E类地址:1111结尾 子网掩码就是网络号为1,主机号位0的一串01组合。主机的IP地址和子网掩码的逻辑与就是网络地址利用一:就是通过主机IP地址和子网掩码计算网络地址例子:某主机的IP地址为210.33.5.68,子网掩码为:255.255.255.128,计算其网络地址?解答:210.33.5.68and 255.255.255.128后果:210.33.5.0利用二:已知某网络的子网掩码求其划分的子网数目。例子:已知某A类网络20.0.0.0的子网掩码为255.224.0.0,请确定划分的子网数目?并写出每个子网的子网号?解答:咱们已知A类网络的默认子网掩码是255.0.0.0,依据题目咱们晓得,子网掩码的第二个字节为224,写成二进制就是:11100000,咱们能够看到,该A类网络应用第二个字节的前三位进行了子网划分,所以他的子网数目就是2^3=8个这8个子网的子网号别离是:20.000 00000.0.0|20.0.0.020.001 00000.0.0|20.32.0.020.010 00000.0.0|20.64.0.020.011 00000.0.0|20.96.0.020.100 00000.0.0|20.128.0.020.101 00000.0.0|20.160.0.020.110 00000.0.0|20.192.0.020.111 00000.0.0|20.224.0.0利用三: 解答:c类网络的默认子网掩码是255.255.255.0,已知要将其划分为4个子网,那么就须要占用2个主机位,那么子网掩码就是255.255.255.11 000000=255.255.255.192每个子网的无效主机IP地址为:200.161.30.00 000001-200.161.30.00 111110(进来全0和全1)其余子网相似。利用四: 解答:已知该网络地址是c类地址:要划分5个子公司也就是5个子网,也就须要3位来进行子网划分,c、类地址最初一个字节是8位,除掉3位用于子网号的还剩5位,2^5-2=30>28满足最大要求。所以子网掩码是:255.255.255.2248个子网的子网地址:

July 30, 2020 · 1 min · jiezi

关于面试:剑指offer-阅读笔记三数据结构之数组

排版如果影响浏览能够 浏览原文 数组能够说是最简略的一种数据结构,它占据一块间断的内存并依照顺序存储数据。 创立数组时,须要先指定数组容器的大小,而后依据大小分配内存。 因为数组的内存是间断的,于是能够依据下标在O(1)工夫读写任何元素,因而它的工夫效率很高。 依据数组工夫效率高的长处, 实现简略的哈希表,用数组来实现简略的哈希表,把数组的下标设为哈希表的键,数组元素为哈希表的值, 有了这样的哈希表,咱们能够在O(1)工夫内查找。 为了解决数组空间效率不高的问题,人们又设计实现了多种动静数组,比方c++中的STL中的vector,为了避免浪费,先为数组开拓较小的空间,而后往数组中增加数组。 当数组的数据超过数组容量时,咱们再重新分配一块更大的空间(c++ 中vector 为之前的两倍,python list也为之前的两倍),把之前的数据复制到新数组中,再把之前的内存开释。 这对工夫性能有负面影响,因而应用动静数组时要尽量减少扭转数组容量大小的次数。 关键点1在c/c++中,数组和指针是既相干又有区别的概念,当咱们申明一个数组时,其数组的名字也是一个指针,该指针指向数组的第一个元素。咱们能够用指针来拜访数组。 c/c++没有记录数组的大小,因而在拜访数组元素时,程序员要确保没有超出数组的边界。 运行上面代码,请问输入什么? #include <iostream>using namespace std;int GetSize(int data[]){return sizeof(data);}int main(int argc, const char* argv[]){int data1[] = {1, 2, 3, 4, 5};int size1 = sizeof(data1);int* data2 = data1;int size2 = sizeof(data2);int size3 = GetSize(data1);cout << size1 << endl << size2 << endl << size3 << endl;return 0;}答案是: 20, 8, 8,data是一个数组,sizeof(data)求的是数组的大小,5个整数,每个整数占4个字节,因而占20个字节。 data2是指针,指针在32位操作系统上占4位,64位操作系统占8位。在c/c++中,当数组当作函数的参数进行传递时,数组就主动进化为同类型的指针。因而,只管函数GetSize的参数data被申明为数组,但他会进化为指针。 面试题3:找出数组中反复的数字在一个长度为n的数组里的所有数字都在0~n-1的范畴内。数组中某些数字是反复的,然而不晓得有几个数字是反复的了,也不晓得数字反复了几次。请找出数组中任意一个反复的数字。例如,如果输出长度为7的数组{2,3,1,0,2,5,3},那么对应的输入反复的数字2或者3。 ...

July 20, 2020 · 2 min · jiezi

关于面试:分享下我在56月份求职的面经php

汇总最近一两个月,我别离加入了力拓飞远,最右app,轻松筹,大搜车,360,立思辰,微淼商学院,滴滴,百度,字节跳动,现实汽车的在线/电话面试,回绝了小熊美家,小叶子TheOne,作业帮,世纪佳缘的到场面试。总结上面试题和面试教训,我的经验,与君分享。 殊途同归的面试题nginx:epoll模型nginx和fpm的交互流程有哪些优化项负载平衡策略和比照限流 mysql:锁机制,索引,事务,隔离级别和对应解决的问题。sql查问优化,以及explain打算。mysql比拟常见的细节问题,比方:innodb的特点,Hash索引和B+树区别,非聚簇索引和回表查问,以及写sql能力的考查。 算法:全排列,各种排序,二分查找。 操作系统:过程状态,IPC,调度算法,线程和协程,死锁。 计算机网络:五层别离哪些。tcp、udp区别。同源测略和跨域。一个网页从输出地址回车,到残缺展现网页内容这段时间里,做了哪些工作。keepalived是什么,有什么作用(tcp)。cdn如何防篡改,https如何平安。 Redis:应用场景,淘汰策略,长久化,主从哨兵和底层实现。 php:zval构造,垃圾回收,7新个性,get|post,session,cookie,字符串,数组函数的用法,命名空间,composerfpm的优化,三种配置形式,动态形式如何确定最大worker数 业务相干的问题:接口设计,鉴权局部设计,单点,单用户,高并发,防超卖,Saas我的项目架构设计。 开放式的问题:请简略介绍一下你做的这个我的项目近期遇到比拟辣手的问题、有挑战性的问题,你是如何去解决这个问题的。 尺有所短,寸有所长最右app一面挂。微信视频面。面试的第一家公司,过后没怎么筹备面试,一面和面试官聊了下,他倡议我多补充下根底,再面试。最初聊了下工作和学习心得。 力拓飞远一面挂。我,面试官,hr三者视频在线面试。也是刚开始找工作时候面试的公司,没有什么筹备,一上来让自我介绍,也没能提前准备好,感觉说的个别。而后没面我的技术,开始诘问我有没有写博客,开源我的项目,我感觉简历上都写了,于是间接说简历上有,从对方语气感觉有不悦。于是我就反诘你有博客,或者github开源我的项目么,分享下吧,面试官面色一下难看了,hr打了个圆场,不欢而散。 预先自省了下: 有些话术还是要提前准备好。面试也是个双选的过程。轻松筹二面挂,电话面。只问了mysql和redis,其中有问到,同一个字段,用int还是char查问效率高。隔离级别问的比拟细,有问到间隙锁是什么,解决了什么问题,以及mvcc。以及Nginx理论工作优化,,php-fpm理论工作配置的优化。因为我简历有es,问到如何向ES集群插入百万级别数据。他们php曾经转GO了,抉择的是echo框架。 大搜车在线做题挂,未加入面试。nginx 502,503,504个别是nginx或者fastcgi网关出什么问题,如何解决。除了nginx的一题没有答上来,其余的全副写答案了,感觉还OK,然而没有让我加入面试,也没给我起因,不晓得那边打算要什么样的人才。 现实汽车一面挂。电话面。laravel框架的运行流程,了解。过程间通信-文件和文件锁。怎么测算qps。怎么晓得你的机器的最大承载是多少。 360搜寻部门。电话面试。二面挂。问到了OOP个性和解决问题,我感觉大学学的是:封装,集成,多态。面试官说,再想想????????,最初面试官通知我还有:多态。这个感觉很玄学,如果问OOP个性,应该是三个,如果问特色,应该是4个。其余的问了一些平安方面的,比方:csrf,ssrf,xss,sql注入,ddos等等。 滴滴二面挂。微信视频面。一面是个姑娘, 感觉很nice,问的问题都是常见面试题。最初反诘环节,问了些滴滴的技术栈,php和go并重。二面面试官,问了些nginx的问题,感觉答的还OK,感觉是个php的动摇支持者,面了一个小时,我说go有比php强的一面,所以当初很多公司转go,面试官不乐意,说php-fpm的IO模型更好,不在发问,我感觉挂在面试官集体情绪上了。 字节跳动AI Lab&data部门,二面挂,zoom视频会议面试。面试官是个java工程师,转go,感觉面试题出的很仓促,对方没有筹备面试。什么是hashmap。什么是函数式编程。说一说并发和锁。尽可能多的说你晓得的设计模式。最初问了个智力题,理论是算法(考查有序数组,字典的使用), 写完之后,问工夫复杂度。设计一个LRU的缓存零碎。设计一个过程池。 立思辰三面过,offer。常见问题居多。业务问题:如何设计一个反对十几条业务线的短信发送服务,想到方面越多越好,幂等防重发,防超时,平安,权限验证,成功率,异步,等等状况。 微淼商学院六面过,offer。公司在神州数码大厦,挨着西二旗地铁口,地位很不错,,hr说公司规模1000到2000人,技术团队30多人,感觉很不匹配。如何获取用户的实在ip。简单sql编写的考查。索引存储在磁盘的构造。b树,红黑二叉树,b-,b+。如何设计反对退款和各种优惠活动的订单相干数据库表。视频课程防盗版的教训。redis分布式事务。音讯队列在业务中的应用考查。 某度六面过,offer。问了一些海量数据处理的问题,比方: 两个亿级别数据量的表,字段雷同,数据绝大多数雷同,只有几条数据不同,如何疾速找出两个表外面数据不同的那几条。剖析nginx日志,海量数据外面找出拜访次数排名前十的IP。一些题目的答案phper面试-2020 我的笔记web开发者常识体系

July 20, 2020 · 1 min · jiezi

关于面试:如何准备面试进大厂

说说近况:最近太忙了,根本10-2-7的节奏,不仅仅是工作,技术的钻研,还有团体的编程较量,正好这周告一段落,略微好了一点。这几个月有不少人找我征询如何能力进入大厂,这边我也简略随笔聊一下这个话题我置信有不少人比拟迷茫,本人每天写点业务代码,还常常加班导致越下班技术越low,市场竞争力越来越低,还有很多人存在一年教训用很多年的状况;这样的状况普遍存在,这外面就蕴含很多在小公司的人,感觉也没有啥能进步的,想要破局,想进入大厂,至多大厂有一群优良的人,大厂技术水平很不错,当然这是我接触到的这部分人的想法。 如何破局呢? 我之前也写过一篇付费文章对于破局的思路 年薪50W以上的破局之法,也提了一些点,感兴趣的能够看下,但这里就不怎么具体说破局了。 我这里就简略说说如何筹备面试进大厂? 首先须要一个好的简历,一个看上去还不错的简历,所以批改简历是第一步。 可能有人说学校不好啊,公司个别,做的我的项目个别啊,怎么可能让本人简历还不错呢?不可能吧。不是这样的,其实你用心去批改筹备简历,还是能达到不错的成果的。除非你这几年工作真的是白混了,除非你一点也不筹备筹备。其实简历写的货色,你短时间也是能够好好筹备的。比如说你相熟rocketmq源码存储这一块,就算你之前没理解过,你也能够好好的最近去筹备下,钻研下,而后在你的简历上写上去,说看过这块源码之类,这难道不就是加分项吗?还有就是比方你简历上写到:  做了xx零碎的开发,做了什么什么性能,优化了xxx性能。这个简历当然很一般,但你一改,比如说:  负责xx零碎的开发,作为外围程序员,岂但实现了xxx性能的工作,更提出了xxxx的改良计划,极大晋升了xxx效率,从10QPS晋升200QPS。当然这是一个例子,那你感觉是不是看上去好多了,所以用心批改简历也是能让简历达到一种不错的样子。当然这外面办法策略很多,就不一一道来了。感兴趣的同学能够在文尾加我微信与我一起交换交换。 当你简历批改好了,其次就是怎么去好好筹备了,筹备也是要肯定办法策略的;首先你要针对你的简历好好筹备下,因为面试就是要依据你的简历去发问的,所以这个是必须要相熟,外面会波及业务架构,业务零碎的复杂性,你在外面解决了什么问题,优化了什么,技术挑战度如何,面试都是要思考的,所以你能够依据这个去好好的思考下你的业务我的项目; 对了,根底这个是特地重要的,比如说你面试JAVA程序员岗位,对应的JVM,数据库,并发等等必定是要筹备的,当初网上这块常识整顿也比拟多,去学习,不便多了。刚刚业务我的项目这块,除了下面讲的,接着就是业务波及的技术点,比如说redis,那对应你为啥用redis,而不是其余的,用到它的什么个性,怎么用的,有什么益处?带来什么价值?又有什么问题呢?都是要思考的。 还有你的人才特质,比如说怎么突出你学习能力,业务sense,技术激情,沟通能力,钻研能力等等。这个怎么说呢,也是要考查的点,大厂HRG对这块其实看的还是十分重要的,所以说这块你一不注意是会被间接pass的。这块提前也是能够想想,筹备下的。 其实如何筹备面试进大厂?我感觉相对而言其实不是很难,要害平时工作是否用心去思考,或者是否你用心去花工夫筹备面试,如果两个都没有去做到,那就别想了。过后长期去筹备面试,往往也能起到很大的作用;很多人说只有面试的时候,本人才会有特地大的压力去好好的学习,好好的筹备,学习的货色比一年学习的货色还多,是有肯定情理的。所以说筹备的重要性,当然这个外面会波及很多办法,策略,当前前面针对公司的应答性筹备等等,这都是须要去思考的,这外面如果有曾经在大厂的人指导,或者说在大厂负责面试的人去指导倡议下,可能会事倍功半。 当然我写的这篇文章比拟随便,相对而言比拟浅,外面波及的很多货色,因为工夫问题,没有一一道来。想理解更多的同学,能够加我微信 hangzhoushoot 找我征询领导。 目前在阿里团体 做低代码开发平台,感兴趣的同学能够投递简历到我的邮箱  edagarli@126.com  或者加我微信hangzhoushoot ;阿里秋招也开始了,欢送优良的实习生投递简历来实习,一起为这个世界做出一点扭转。 (如果想要学习理解更多的内容,能够关注我的公众号)

July 20, 2020 · 1 min · jiezi

关于面试:2020面试题

1.商越网络 1.beanFactory和FactoryBean的区别? 2.spring boot的前端解析流程?

July 19, 2020 · 1 min · jiezi

这份Github神仙笔记覆盖了90以上的Java面试题带你所向披靡

前言作为一个 Java 程序员,你平时总是陷在业务开发里,每天噼里啪啦忙敲着代码,上到零碎开发,下到 Bug 批改,你感觉本人无所不能。然而偶然的一次团聚,你据说和本人一起出道的同学早曾经年薪 50 万,而本人却囊中羞涩。于是你也想看看新机会,找个新平台,好好倒退。 然而面试的时候,当那个笑眯眯的面试官问出那些你再相熟不过的 Java 问题时,你只是感觉似曾相识,却怎么也答复不到点上。比方 HashMap 的工作原理,再或者 volatile 的应用场景。 这个时候,你可能会狐疑本人的能力,也痛恨为什么当初本人没有好好温习。 该新版文档在Github上上传一个星期曾经播种30K+star的Java外围面试神技(这参数,品质多高就不必我多说了吧)十分全面,包涵Java根底、Java汇合、JavaWeb、Java异样、OOP、IO与NIO、反射、注解、多线程、JVM、MySQL、MongoDB、Spring全家桶、计算机网络、分布式架构、Redis、Linux、git、前端、算法与数据结构、MyBatis、RocketMQ、Netty、Dubbo、Zookeeper、分布式缓存、数据结构等等内容十分丰盛,曾经帮很多人拿下互联网一线公司的offer。上面我来跟大家一起分享一下。文末有支付形式JavaOOP什么是B/S架构?什么是C/S架构Java都有哪些开发平台?什么是JDK?什么是JRE?Java语言有哪些特点面向对象和面向过程的区别什么是数据结构?Java的数据结构有哪些?什么是OOP?类与对象的关系?Java中有几种数据类型 Java汇合/泛型ArrayList和linkedList的区别HashMap和HashTable的区别Collection包构造,与Collections的区别泛型罕用特点 (待补充)说说List,Set,Map三者的区别Array与ArrayList有什么不一样?Map有什么特点汇合内寄存于 Java.util 包中, 次要有几 种接口什么是list接口说说ArrayList(数组) 因为文档里的细节内容切实过多所以只编辑了局部知识点的章节粗略的介绍下,每个章节小节点外面都有更细化的内容!以下就是局部章节目录,因为头条的篇幅限度目录上的具体解说也无奈一一列出,文末底下有获取以下章节的所有具体常识解说。文末有支付形式Java异样Java中异样分为哪两种?异样的解决机制有几种?如何自定义一个异样try catch fifinally,try里有return,finally还执行么?Excption与Error包构造Thow与thorws区别Error与Exception区别?error和exception有什么区别 Java中的IO与NIOJava 中 IO 流?Java IO与 NIO的区别罕用io类有哪些字节流与字符流的区别阻塞 IO 模型非阻塞 IO 模型多路复用 IO 模型信号驱动 IO 模型异步 IO 模型JAVA NIO Java反射除了应用new创建对象之外,还能够用什么办法创建对象?Java反射创建对象效率高还是通过new创建对象的效率高?java反射的作用哪里会用到反射机制?反射的实现形式:实现Java反射的类:反射机制的优缺点:Java 反射 API反射应用步骤(获取 Class 对象、调用对象办法)获取 Class 对象有几种办法利用反射动静创建对象实例 Java序列化什么是java序列化,如何实现java序列化?保留(长久化)对象及其状态到内存或者磁盘序列化对象以字节数组放弃-动态成员不保留序列化用户近程对象传输Serializable 实现序列化writeObject 和 readObject 自定义序列化策略序列化 ID序列化并不保留动态变量Transient 关键字阻止该变量被序列化到文件中序列化(深 clone 一中实现) 多线程&并发JAVA 并发知识库 Java中实现多线程有几种办法继承 Thread 类实现 Runnable 接口。ExecutorService、 Callable、 Future 有返回值线程基于线程池的形式4 种线程池如何进行一个正在运行的线程notify()和notifyAll()有什么区别?sleep()和wait() 有什么区别?volatile 是什么?能够保障有序性吗? ...

July 10, 2020 · 2 min · jiezi

面试题

July 10, 2020 · 0 min · jiezi

面试官常问的31道Java核心面试题熬夜整理好送给你

这次我花了一周的工夫,筹备了 31 道 Java 外围面试题,心愿可能帮忙到读者。01、请说出 Java 14 版本中更新的重要性能Java 14 公布于 2020 年 3 月 17 日,更新的重要性能有:switch 表达式instanceof 加强表达式,预览性能文本块,第二次预览Records,预览性能02、请说出 Java 13 版本中更新的重要性能Java 13 公布于 2019 年 9 月 17 日,更新的重要性能有:文本块,预览性能switch 表达式,预览性能Java Socket 从新实现FileSystems.newFileSystem() 办法反对 Unicode 12.1可伸缩、低提早的垃圾收集器改良,用于返回未应用的内存03、请说出 Java 12 版本中更新的重要性能Java 12 公布于 2019 年 3 月 19 日,更新的重要性能有:JVM 更新File.mismatch() 办法紧凑型数字格局String 类新增了一些办法,比如说 indent()04、请说出 Java 11 版本中更新的重要性能Java 11 是继 Java 8 之后的第二个商用版本,如果你下载的是 Oracle JDK,则须要进行付费;如果想持续应用收费版本,须要下载 Open JDK。Oracle JDK 中会有一些 Open JDK 没有的、商用闭源的性能。Java 11 更新的重要性能有:能够间接应用 java 命令运行 Java 程序,源代码将会隐式编译和运行。String 类新增了一些办法,比如说 isBlank()、lines()、strip() 等等。Files 类新增了两个读写办法,readString() 和 writeString()。能够在 Lambda 表达式中应用 var 作为变量类型。05、请说出 Java 10 版本中更新的重要性能Java 10 更新的重要性能有:局部变量类型推断,举个例子,var list = new ArrayList();,能够应用 var 来作为变量类型,Java 编译器晓得 list 的类型为字符串的 ArrayList。加强 java.util.Locale。提供了一组默认的根证书颁发机构(CA)。06、请说出 Java 9 版本中更新的重要性能Java 9 更新的重要性能有:模块零碎不可变的 List、Set、Map 的工厂办法接口中能够有公有办法垃圾收集器改良07、请说出 Java 8 版本中更新的重要性能Java 8 公布于 2014 年 3 月份,能够说是 Java 6 之后最重要的版本更新,深受开发者的青睐。函数式编程和 Lambda 表达式Stream 流Java Date Time API接口中能够应用默认办法和静态方法我强烈建议点开下面的链接浏览以下,以正确理解这些概念。08、请说出 Java 面向对象编程中的一些重要概念形象封装多态继承09、Java 宣称的平台独立性指的是什么?常见的操作系统有 Windows、Linux、OS-X,那么平台独立性意味着咱们能够在任何操作系统中运行雷同源代码的 Java 程序,比如说咱们能够在 Windows 上编写 Java 程序,而后在 Linux 上运行它。10、什么是 JVM?JVM(Java Virtual Machine)俗称 Java 虚拟机。之所以称为虚拟机,是因为它实际上并不存在。它提供了一种运行环境,可供 Java 字节码在下面运行。JVM 提供了以下操作:加载字节码验证字节码执行字节码提供运行时环境JVM 定义了以下内容:存储区类文件格式寄存器组垃圾回收堆致命错误报告等咱们来尝试了解一下 JVM 的内部结构,它蕴含了类加载器(Class Loader)、运行时数据区(Runtime Data Areas)和执行引擎(Excution Engine)。1)类加载器类加载器是 JVM 的一个子系统,用于加载类文件。每当咱们运行一个 Java 程序,它都会由类加载器首先加载。Java 中有三个内置的类加载器:启动类加载器(Bootstrap Class-Loader),加载 jrelib 包上面的 jar 文件,比如说常见的 rt.jar(蕴含了 Java 规范库下的所有类文件,比如说 java.lang 包下的类,java.net 包下的类,java.util 包下的类,java.io 包下的类,java.sql 包下的类)。扩大类加载器(Extension or Ext Class-Loader),加载 jrelibext 包上面的 jar 文件。利用类加载器(Application or App Clas-Loader),依据程序的类门路(classpath)来加载 Java 类。一般来说,Java 程序员并不需要间接同类加载器进行交互。JVM 默认的行为就曾经足够满足大多数状况的需要了。不过,如果遇到了须要和类加载器进行交互的状况,而对类加载器的机制又不是很理解的话,就不得不花大量的工夫去调试ClassNotFoundException 和 NoClassDefFoundError 等异样。对于任意一个类,都须要由它的类加载器和这个类自身一起确定其在 JVM 中的唯一性。也就是说,如果两个类的加载器不同,即便两个类来源于同一个字节码文件,那这两个类就必然不相等(比方两个类的 Class 对象不 equals)。是不是有点晕,来来来,通过一段简略的代码理解下。public class Test {    public static void main(String[] args) {        ClassLoader loader = Test.class.getClassLoader();        while (loader != null) {            System.out.println(loader.toString());            loader = loader.getParent();        }    }}每个 Java 类都保护着一个指向定义它的类加载器的援用,通过 类名.class.getClassLoader() 能够获取到此援用;而后通过 loader.getParent() 能够获取类加载器的下层类加载器。下面这段代码的输入后果如下:sun.misc.Launcher$AppClassLoader@18b4aac2sun.misc.Launcher$ExtClassLoader@4617c264第一行输入为 Test 的类加载器,即利用类加载器,它是 sun.misc.Launcher$AppClassLoader 类的实例;第二行输入为扩大类加载器,是 sun.misc.Launcher$ExtClassLoader 类的实例。那启动类加载器呢?按理说,扩大类加载器的下层类加载器是启动类加载器,但在我这个版本的 JDK 中, 扩大类加载器的 getParent() 返回 null。所以没有输入。2)运行时数据区运行时数据区又蕴含以下内容。PC寄存器(PC Register),也叫程序计数器(Program Counter Register),是一块较小的内存空间,它的作用能够看做是以后线程所执行的字节码的信号指示器。JVM 栈(Java Virtual Machine Stack),与 PC 寄存器一样,JVM 栈也是线程公有的。每一个 JVM 线程都有本人的 JVM 栈,这个栈与线程同时创立,它的生命周期与线程雷同。本地办法栈(Native Method Stack),JVM 可能会应用到传统的栈来反对 Native 办法(应用 Java 语言以外的其它语言[C语言]编写的办法)的执行,这个栈就是本地办法栈。堆(Heap),在 JVM 中,堆是可供各条线程共享的运行时内存区域,也是供所有类实例和数据对象分配内存的区域。办法区(Method area),在 JVM 中,被加载类型的信息都保留在办法区中。包含类型信息(Type Information)和办法列表(Method Tables)。办法区是所有线程共享的,所以拜访办法区信息的办法必须是线程平安的。运行时常量池(Runtime Constant Pool),运行时常量池是每一个类或接口的常量池在运行时的表现形式,它包含了编译器可知的数值字面量,以及运行期解析后能力取得的办法或字段的援用。简而言之,当一个办法或者变量被援用时,JVM 通过运行时常量区来查找办法或者变量在内存里的理论地址。3)执行引擎执行引擎蕴含了:解释器:读取字节码流,而后执行指令。因为它一条一条地解释和执行指令,所以它能够很快地解释字节码,然而执行起来会比较慢。即时(Just-In-Time,JIT)编译器:即时编译器用来补救解释器的毛病,进步性能。执行引擎首先依照解释执行的形式来执行,而后在适合的时候,即时编译器把整段字节码编译成本地代码。而后,执行引擎就没有必要再去解释执行办法了,它能够间接通过本地代码去执行。执行本地代码比一条一条进行解释执行的速度快很多。编译后的代码能够执行的很快,因为本地代码是保留在缓存里的。11、JDK 和 JVM 有什么区别?JDK 是 Java Development Kit 的首字母缩写,是提供给 Java 开发人员的软件环境,蕴含 JRE 和一组开发工具。可分为以下版本:标准版(大多数开发人员用的就是这个)企业版微型版JDK 蕴含了一个公有的 JVM 和一些其余资源,比如说编译器(javac 命令)、解释器(java 命令)等,帮忙 Java 程序员实现开发工作。12、JVM 和 JRE 有什么区别?Java Runtime Environment(JRE)是 JVM 的实现。JRE 由 JVM 和 Java 二进制文件以及其余类组成,能够执行任何程序。JRE 不蕴含 Java 编译器,调试器等任何开发工具。13、哪个类是所有类的超类?java.lang.Object 是所有 Java 类的超类,咱们不须要继承它,因为是隐式继承的。14、为什么 Java 不反对多重继承?如果有两个类独特继承(extends)一个有特定办法的父类,那么该办法会被两个子类重写。而后,如果你决定同时继承这两个子类,那么在你调用该重写办法时,编译器不能辨认你要调用哪个子类的办法。这也正是驰名的菱形问题,见下图。ClassC 同时继承了 ClassA 和 ClassB,ClassC 的对象在调用 ClassA 和 ClassB 中重载的办法时,就不晓得该调用 ClassA 的办法,还是 ClassB 的办法。15、为什么 Java 不是纯正的面向对象编程语言?之所以不能说 Java 是纯正的面向对象编程语言,是因为 Java 反对根本数据类型,比如说 int、short、long、double 等,只管它们有本人的包装器类型,但它们确实不能算是对象。16、path 和 classpath 之间有什么区别?path 是操作系统用来查找可执行文件的环境变量,我的电脑上就定义了下图这些 path 变量,比方 Java 和 Maven 的。classpath 是针对 Java 而言的,用于指定 Java 虚拟机载入的字节码文件门路。17、Java 中 `main()` 办法的重要性是什么?每个程序都须要一个入口,对于 Java 程序来说,入口就是 main 办法。public static void main(String[] args) {}public 关键字是另外一个拜访修饰符,除了能够申明办法和变量(所有类可见),还能够申明类。main() 办法必须申明为 public。static 关键字示意该变量或办法是动态变量或静态方法,能够间接通过类拜访,不须要实例化对象来拜访。void 关键字用于指定办法没有返回值。另外,main 关键字为办法的名字,Java 虚拟机在执行程序时会寻找这个标识符;args 为 main() 办法的参数名,它的类型为一个 String 数组,也就是说,在应用 java 命令执行程序的时候,能够给 main() 办法传递字符串数组作为参数。java HelloWorld xuanwo008javac 命令用来编译程序,java 命令用来执行程序,HelloWorld 为这段程序的类名,缄默王二和缄默王三为字符串数组,两头通过空格隔开,而后就能够在 main() 办法中通过 args[0] 和 args[1] 获取传递的参数值了。public class HelloWorld {    public static void main(String[] args) {        if ("xuanwo008".equals(args[0])) {        }        if ("xuanwo008".equals(args[1])) {        }    }}main() 办法的写法并不是惟一的,还有其余几种变体,只管它们可能并不常见,能够简略来理解一下。第二种,把方括号 [] 往 args 凑近而不是 String 凑近:public static void main(String []args) { }第三种,把方括号 [] 放在 args 的右侧:public static void main(String args[]) { }第四种,还能够把数组模式换成可变参数的模式:public static void main(String...args) { }第五种,在 main() 办法上增加另外一个修饰符 strictfp,用于强调在解决浮点数时的兼容性:public strictfp static void main(String[] args) { }也能够在 main() 办法上增加 final 关键字或者 synchronized 关键字。第六种,还能够为 args 参数增加 final 关键字:public static void main(final String[] args) { }第七种,最简单的一种,所有能够增加的关键字通通增加上:final static synchronized strictfp void main(final String[] args) { }当然了,并不需要为了装逼特意把 main() 办法写成下面提到的这些模式,应用 IDE 提供的默认模式就能够了。18、Java 的重写(Override)和重载(Overload)有什么区别?先来看一段重写的代码吧。class LaoWang{    public void write() {        System.out.println("老王写了一本《基督山伯爵》");    }}public class XiaoWang extends LaoWang {    @Override    public void write() {        System.out.println("小王写了一本《茶花女》");    }}重写的两个办法名雷同,办法参数的个数也雷同;不过一个办法在父类中,另外一个在子类中。就如同父类 LaoWang 有一个 write() 办法(无参),办法体是写一本《基督山伯爵》;子类 XiaoWang 重写了父类的 write() 办法(无参),但办法体是写一本《茶花女》。来写一段测试代码。public class OverridingTest {    public static void main(String[] args) {        LaoWang wang = new XiaoWang();        wang.write();    }}大家猜后果是什么?小王写了一本《茶花女》在下面的代码中,们申明了一个类型为 LaoWang 的变量 wang。在编译期间,编译器会查看 LaoWang 类是否蕴含了 write() 办法,发现 LaoWang 类有,于是编译通过。在运行期间,new 了一个 XiaoWang 对象,并将其赋值给 wang,此时 Java 虚拟机晓得 wang 援用的是 XiaoWang 对象,所以调用的是子类 XiaoWang 中的 write() 办法而不是父类 LaoWang 中的 write() 办法,因而输入后果为“小王写了一本《茶花女》”。再来看一段重载的代码吧。class LaoWang{    public void read() {        System.out.println("老王读了一本《Web全栈开发进阶之路》");    }    public void read(String bookname) {        System.out.println("老王读了一本《" + bookname + "》");    }}重载的两个办法名雷同,但办法参数的个数不同,另外也不波及到继承,两个办法在同一个类中。就如同类 LaoWang 有两个办法,名字都是 read(),但一个有参数(书名),另外一个没有(只能读写死的一本书)。来写一段测试代码。public class OverloadingTest {    public static void main(String[] args) {        LaoWang wang = new LaoWang();        wang.read();        wang.read("金瓶梅");    }}这后果就不必猜了。变量 wang 的类型为 LaoWang,wang.read() 调用的是无参的 read() 办法,因而先输入“老王读了一本《Web全栈开发进阶之路》”;wang.read("金瓶") 调用的是有参的 read(bookname) 办法,因而后输入“老王读了一本《金瓶》”。在编译期间,编译器就晓得这两个 read() 办法时不同的,因为它们的办法签名(=办法名称+办法参数)不同。简略的来总结一下:1)编译器无奈决定调用哪个重写的办法,因为只从变量的类型上是无奈做出判断的,要在运行时能力决定;但编译器能够明确地晓得该调用哪个重载的办法,因为援用类型是确定的,参数个数决定了该调用哪个办法。2)多态针对的是重写,而不是重载。如果在一个类中有多个雷同名字的办法,但参数不同,则称为办法重载。父类中有一个办法,子类中有另外一个和它有雷同签名(办法名雷同,参数雷同、修饰符雷同)的办法时,则称为办法重写。子类在重写父类办法的时候能够加一个 @Override 注解。19、`main()` 办法能够重载吗?能够,一个类中能够有多个名称为“main”的办法:public class MainTest {    public static void main(String[] args) {        System.out.println("main(String[] args)");    }    public static void main(String[] args,String arg) {        System.out.println("(String[] args,String arg");    }}但该类在运行的时候,只会找到一个入口,即 public static void main(String[] args)。20、一个 Java 源文件中有多个 public 类吗?一个 Java 源文件中不能有多个 public 类。21、什么是 Java 的 package(包)?在 Java 中,咱们应用 package(包)对相干的类、接口和子包进行分组。这样做的益处有:使相干类型更容易查找防止命名抵触,比如说 com.itwanger.Hello 和 com.itwangsan.Hello 不同通过包和拜访权限控制符来限定类的可见性能够应用 package 关键字来定义一个包名,须要留神的是,这行代码必须处于一个类中的第一行。强烈建议在包中申明类,不要缺省,否则就失去了包构造的带来的益处。包的命名应该恪守以下规定:应该全副是小写字母能够蕴含多个单词,单词之间应用“.”连贯,比如说 java.lang名称由公司名或者组织名确定,采纳倒序的形式,比如说,我集体博客的域名是 www.itwanger.com,所以我创立的包名是就是 com.itwanger.xxxx。每个包或者子包都在磁盘上有本人的目录构造,如果 Java 文件时在 com.itwanger.xxxx 包下,那么该文件所在的目录构造就应该是 com->itwanger->xxxx。默认状况下,java.lang 包是默认导入的,咱们不须要显式地导入该包下的任何类。package com.cmower.bb;public class PackageTest {    public static void main(String[] args) {        Boolean.toString(true);    }}Boolean 类属于 java.lang 包,当应用它的时候并不需要显式导入。22、什么是拜访权限修饰符?拜访权限修饰符对于 Java 来说,十分重要,目前共有四种:public、private、protected 和 default(缺省)。一个类只能应用 public 或者 default 润饰,public 润饰的类你之前曾经见到过了,当初我来定义一个缺省权限修饰符的类给你观赏一下。class Dog {}哈哈,其实也没啥能够观赏的。缺省意味着这个类能够被同一个包下的其余类进行拜访;而 public 意味着这个类能够被所有包下的类进行拜访。如果硬要通过 private 和 protected 来润饰类的话,编译器会怄气的,它不批准。private 能够用来润饰类的构造方法、字段和办法,只能被以后类进行拜访。protected 也能够用来润饰类的构造方法、字段和办法,但它的权限范畴更宽一些,能够被同一个包中的类进行拜访,或者以后类的子类。能够通过上面这张图来比照一下四个权限修饰符之间的差异:同一个类中,不论是哪种权限修饰符,都能够拜访;同一个包下,private 润饰的无法访问;子类能够拜访 public 和 protected 润饰的;public 修饰符面向世界,哈哈,能够被所有的中央拜访到。23、什么是 final 关键字?final 关键字润饰类的时候,示意该类无奈被继承。比方,String 类就是 final 的,无奈被继承。final 关键字润饰办法的时候,示意子类无奈笼罩它。final 关键字润饰变量的时候,示意该变量只能被赋值一次,只管变量的状态能够更改。对于 final 更具体的内容,能够参照我之前写了另外一篇文章:我去,你居然还不会用 final 关键字24、什么是 static 关键字?static 关键字能够用来润饰类变量,使其具备全局性,即所有对象将共享同一个变量。static 关键字能够用来润饰办法,该办法称为静态方法,只能够拜访类的动态变量,并且只能调用类的静态方法。对于 static 更具体的内容,能够参照我之前写了另外一篇文章:面试官:兄弟,说说Java的static关键字吧25、finally 和 finalize 有什么区别?finally 通常与 try-catch 块一起应用,即便 try-catch 块引发了异样,finally 块中的代码也会被执行,用于开释 try 块中创立的资源。finalize() 是 Object 类的一个非凡办法,当对象正在被垃圾回收时,垃圾收集器将会调用该办法。能够重写该办法用于开释系统资源。26、能够将一个类申明为 static 的吗?不能将一个外部类申明为 static 的,但能够将一个外部类申明为 static 的——称为动态外部类。27、什么是动态导入?如果必须在一个类中应用其余类的动态变量或者静态方法,通常咱们须要先导入该类,而后应用“类名.变量办法”的模式调用。import java.lang.Math;double test = Math.PI * 5;也能够通过动态导入的形式,就不须要再应用类名了。import static java.lang.Math.PI;double test = PI * 5;不过,动态导入容易引发凌乱(变量名或者办法名容易抵触),因而最好防止应用动态导入。28、什么是 try-with-resources?try-with-resources 是 Java 7 时引入的一个主动资源管理语句,在此之前,咱们必须通过 try-catch-finally 的形式手动敞开资源,当咱们遗记敞开资源的时候,就容易导致内存透露。对于 try-with-resources 更具体的内容,能够参照我之前写了另外一篇文章:我去,你居然还在用 try–catch-finally29、什么是 multi-catch?Java 7 改良的另外一个中央就是 multi-catch,能够在单个 catch 中捕捉多个异样,当一个 try 块抛出多个相似的异样时,这种写法更短,更清晰。catch(IOException | SQLException ex){     logger.error(ex);     throw new MyException(ex.getMessage());}当有多个异样的时候,能够应用管道示意符“|”隔开。30、什么是 static 块?static 块是由 Java ClassLoader 将类加载到内存中时执行的代码块。通常用于初始化类的动态变量或者创立动态资源。31、什么是接口?接口是 Java 编程语言中的一个外围概念,不仅在 JDK 源码中应用很多,还在 Java 设计模式、框架和工具中应用很多。接口提供了一种在 Java 中实现形象的办法,用于定义子类的行为约定。对于接口更具体的内容,能够参照我之前写了另外一篇文章:可能是把 Java 接口讲得最艰深的一篇文章鸣谢说句实在话,这 31 道 Java 外围面试题在面试的过程中还是很常见的,值得好好温习一遍。因为内容太多,答案我只写了一部分,剩下的已整顿成文档模式上传网盘了,增加VX:xuanwo008即可支付 ...

July 8, 2020 · 3 min · jiezi

程序员面试流程面试游刃有余

电话面试面试官打电话的形式考查应聘者,会提前约好时间有些面试官喜欢搞突然袭击,建议应聘者在投出简历之后的一两个星期之内,保证手机电池能至少连续通话一小时。应聘者不要长时间待在很嘈杂的环境下。电话面试只能依靠声音,描述复杂算法的时候尽可能形象把细节说清楚。 例如,现场面试的时候,如果要描述二叉树的结构,可以用笔在白纸上画出来,电话面试则需要把二叉树中有哪些节点,每个节点的左节点是什么,右节点是什么都说得很清楚。共享桌面面试应聘者把自己的桌面远程分享给面试官,面试官可以观看应聘者编程和调试的过程。面试官关心应聘者的编程习惯及调试能力。 通常面试官会认可以下几个点: 思考清楚再开始编码良好的代码命名和缩进对齐习惯能够进行单元测试现场面试前往公司参加面试之前 规划好路线并估算出行时间,预留半小时缓冲时间应对堵车等意外情况注意面试邀请函里的面试流程。 如果面试有好几轮,时间很长,面试过程可能会觉得疲劳,思维迟钝,可以带些提神饮料。准备几个问题,每轮面试的最后,面试官都会让应聘者提问。准备好得体的衣服面试的3个环节行为面试: 面试官参照简历了解应聘者过往经验。技术面试:要求应聘者现场写代码。应聘者提问。行为面试面试官会注意应聘者的性格特点,深入了解简历中举例的项目经历。 不少面试官会让应聘者做一个简短的自我介绍,由于面试官手拿简历,因此自我介绍不用花很多时间。 用30秒到1分钟的时间介绍自己的主要学习,工作经历即可。 如果面试官对你的经历或项目感兴趣,那么他会有针对性地提问。 应聘者的项目经验建议根据STAR法则描述自己的项目经历。 Situation 简短的项目背景:项目规模,开发的软件功能,目标用户等。Task 自己完成的任务:这个要写详细,要让面试官对自己的工作一目了然,用词上注意区分“参与” 和 “负责”。 “负责”了某个项目,面试官可能会问项目的总体设计,核心算法,团队合作等问题,只是“参与”很难回答。Action 为完成任务自己做了哪些工作,怎么做的。 这里可以详细介绍。 做系统设计的,可以介绍系统架构的特点做软件开发的,可以写基于什么工具在哪个平台下应用了哪些技术做软件测试的,可以写是手工测试还是自动化测试等Result 自己的贡献:这方面的信息可以写的具体些,最好能用数字加以说明。 参与功能开发,则可以说按时完成了多少功能。做优化,则可以说性能提高的百分比是多少如果是维护,则可以说修改了多少个bug举例: winforms是微软.NET 中的一个成熟的UI平台(Situation)。 本人的工作是添加少量新功能之外只要负责维护已有的功能(Task)。新的功能主要是让winforms的控件风格和Vista、windows 7 的风格保持一致。 在维护方面,对于较难的问题,我用winDbg 等工具进行调试(Action)。 在过去的两年中,我共修改了超过200个bug(Result)。如果在应聘者的简历中上述4类信息不够清晰,则面试官可能会追问相关问题。 你在该项目中碰到的最大问题是什么,你是怎么解决的。从这个项目中你学到了什么。什么时候会和其他团队成员,有什么样的冲突,你们是怎么解决的?应聘者在准备简历的时候,针对每一个项目经历都应提前做好相应的准备,只有准备充分,应聘者在行为面试环节才可以表现的游刃有余。 !!! tip 在介绍项目经验(包括在简历上介绍和面试时的口头介绍)时,应聘者不必详述项目的背景,而要突出介绍自己完成的工作以及取得的成绩。 应聘者掌握的技能描述技能的掌握程度时要注意“了解”,“熟悉”,“精通” 的区别。 了解:某项技术只是上过课或者看过书,但没有做过实际的项目。 通常不建议在简历充列出只是肤浅的了解一点的技能,除非这项技术应聘的职位的确需要。熟悉:在实际项目中使用某项技能已经有较长时间,通过查阅相关的文档可以独立解决大部分问题。精通:对某项技能使用得心应手,在项目开发过程中,有同事请教,我们有信心有能力解决。回答“为什么跳槽”面试官通过这个问题来了解应聘者的性格,应聘者可以大胆根据真实想法回答,但也不要想什么说什么,避免留下坏印象。 回答的时候不要抱怨,不要流露负面情绪。 尽量避免以下原因: 老板太苛刻。同事太难相处。加班太频繁。工资太低。 我只管干活,工资公司看着给,相信公司不会亏待勤奋的员工。现在的工作做了一段时间,已经没有太多的激情了,因此希望找一份更有挑战的工作。 具体论证厌倦的原因,以及面试的职位为什么有兴趣。示例: 技术面试 应聘者需要具备的素质 对编程语言、 数据结构和算法等基础知识有全面的了解。面试遇到简单的问题,则一定要注意细节,写出完整、鲁棒的代码。 遇到复杂的问题,可以通过画图,举例子分析和分解复杂问题等方法理清思路再编程。优化时间效率和空间效率,最求找到最优的解法。主动提问,弄清楚题目要求,表现自己的沟通能力。当面试官前后问的两个问题有相关性的时候,尽量把解决问题的思路迁移到后面的问题中去,展示自己良好的学习能力。扎实的基础知识通常基本功再编程面试环节体现在:编程语言、 数据结构、 算法 至少掌握一两门编程语言数据结构是重点,应聘者需要熟练掌握链表,树,栈,队列,哈希表等数据结构,以及他们的操作。 链表,二叉树问得比较多。链表,插入删除二叉树各种遍历方法和递归写法。查找、排序算法 重点掌握二分查找,归并排序和快速排序少数算法很重视的公司还会要求熟练掌握动态规划,贪婪算法。高质量的代码面试官会格外关注边界条件,特殊输入等,看似细枝末节,但实则至关重要。 面试的时候觉得题目很简单,感觉自己都做出来了,可最后为什么被拒了呢? 技能面试的面试官一般都是程序员,程序员通常没有那么多想法,他们只认一个理,题目做对,做完整了,就让你通过,否则失败。 如果遇到简单题目被拒的情况,则应该认真反思在思路或代码中存在哪些漏洞。 !!! tip 面试官除了希望应聘者的代码能够完成基本的功能,还会关注应聘者是否考虑了边界条件,特殊输入(空指针,空字符串等),以及错误处理。 清晰的思路对于复杂的问题,面试官不期待应聘者能在面试不到一小时的时间里给出完整答案,他更看重的还是应聘者是否有清晰的思路。 面试官不喜欢应聘者在没有形成清晰思路之前就草率的开始写代码,这样写出来的代码容易逻辑混乱,错误百出。 应聘者可以用如下几个方法帮组自己形成清晰的思路: ...

July 7, 2020 · 1 min · jiezi

你不会反转链表怎么让面试官对你心动

微信搜索BGM7756,免费获取文末的面试资料!反转链表这题真的是面试非常喜欢考的了,这题看起来简单,但是能用两种方法一遍 bug free 也是不容易的,面试的时候可以筛下来一大批人,无论是对 junior 还是 senior 面试都很爱考。 今天齐姐就带你梳理清楚思路,思路清楚了才能写字如有神。 题目 这是从力扣中文站上截下来的,但是这个输出不太形象。 对链表的反转,并不是要把它实际翻个个,只是动一动 next 指针就好了。 什么意思呢?我们先看对数组进行反转。 数组是一个物理上连续存储的数据结构,反转之后原来放 1 的位置就变成了放 5. 但是链表并不是,因为链表在物理上是不连续的,它的每个单元 ListNode 是通过 next 指针连接在一起的,而每个 ListNode 之间在内存里并不一定是挨着的。 所以反转链表,就不是非要把 1 的位置放 5,因为它们想在哪在哪。 那么怎么保证这个顺序呢? 就是 next 指针。沿着 next 指针的方向走下去,就是链表的顺序。这也就保证了,只要我们拿到了头节点,就掌控了整个 LinkedList. 那么题目中的例子,形象点是这个样子滴: 也就是元素自己不用动,只需要动动小指针,就是反转了。 递归解法递归的三步骤大家还记得吗? Base case + 拆解 + 组合不记得的赶紧在公众号内回复「递归」二字,获取递归的入门篇详解。 那么我们来看这个题的: base case:当只有一个 node,或者没有 node 了呗,也就是 if(node == null || node.next == null) {  return node;}其实呢,只剩一个 node 的时候严格来讲并不是 base case,而是 corner case, 因为它本可以在 break down 到 node == null 的,但因为后面有对 node.next 的 dereference 操作,所以不能省略。 ...

July 7, 2020 · 1 min · jiezi

在java面试中应对分布式锁问题的高招

文末有面试资料福利!面试官:项目中使用过分布式锁吗? 小小白:用过。 面试官:为什么要使用分布式锁? 小小白:为了保证一个方法在高并发情况下的同一时间只能被同一个线程执行,在传统单体应用单机部署的情况下,可以使用Java并发处理相关的API(如ReentrantLcok或synchronized)进行互斥控制。但是,随着业务发展的需要,原单体单机部署的系统被演化成分布式系统后,由于分布式系统多线程、多进程并且分布在不同机器上,这将使原单机部署情况下的并发控制锁策略失效,为了解决这个问题就需要一种跨JVM的互斥机制来控制共享资源的访问,这就是分布式锁要解决的问题。 面试官:项目中用到的分布式锁是你自己实现的,还是别人写的? 小小白:公司中间件部门二次开发的。 面试官:有没有研究过它的具体实现? 小小白:它是在Redisson的基础上再次封装的,因为Redisson已经实现了一套完整的分布式锁解决方案,所以只要做简单的封装就是可以很轻松的使用。 面试官:有没有了解过Redisson实现的分布式锁原理? 小小白:使用key来作为是否上锁的标志,当通过getLock(String key)方法获得相应的锁之后,这个key即作为一个锁存储到Redis集群中,在接下来如果有其他的线程尝试获取名为key的锁时,便会向集群中进行查询,如果能够查到这个锁并发现相应的value的值不为0,则表示已经有其他线程申请了这个锁同时还没有释放,则当前线程进入阻塞,否则由当前线程获取这个锁并将value值加一,如果是可重入锁的话,则当前线程每获得一个自身线程的锁,就将value的值加一,而每释放一个锁则将value值减一,直到减至0,完全释放这个锁。底层通过eval命令来执行Lua脚本,保证复杂业务逻辑执行的原子性。 面试官:如果让你实现一个分布式锁,你会有哪些实现方案? 小小白:这个之前有了解过,基于数据库的实现方式、基于Redis的实现方式和基于ZooKeeper的实现方式。 面试官:使用数据库如何实现? 小小白:在数据库中创建一个表,表中包含方法名等字段,并在方法名字段上创建唯一索引,想要执行某个方法,就使用这个方法名向表中插入数据,成功插入则获取锁,执行完成后删除对应的行数据释放锁。 面试官:据我了解这种实现方案基本没人使用,为什么? 小小白:这种实现方式很简单,但是对于分布式锁应该具备的条件来说,它有一些问题需要解决: 因为是基于数据库实现的,数据库的可用性和性能将直接影响分布式锁的可用性及性能,所以,数据库需要双机部署、数据同步、主备切换;不具备可重入的特性,因为同一个线程在释放锁之前,行数据一直存在,无法再次成功插入数据,所以,需要在表中新增一列,用于记录当前获取到锁的机器和线程信息,在再次获取锁的时候,先查询表中机器和线程信息是否和当前机器和线程相同,若相同则直接获取锁;没有锁失效机制,因为有可能出现成功插入数据后,服务器宕机了,对应的数据没有被删除,当服务恢复后一直获取不到锁,所以,需要在表中新增一列,用于记录失效时间,并且需要有定时任务清除这些失效的数据;不具备阻塞锁特性,获取不到锁直接返回失败,所以需要优化获取逻辑,循环多次去获取。面试官:使用Redis如何实现分布式锁? 小小白:在Redis2.6.12版本之前,使用setnx命令设置key-value、使用expire命令设置key的过期时间获取分布式锁,使用del命令释放分布式锁,但这种实现方式会出现死锁、误删持有的锁、主从机制数据不同步的问题。所以,从Redis2.6.12版本开始,通过SET resource_name my_random_value NX PX max-lock-time来实现分布式锁,这个命令仅在不存在key(resource_name)的时候才能被执行成功(NX选项),并且这个key有一个max-lock-time秒的自动失效时间(PX属性)。这个key的值是“my_random_value”,它是一个随机值,这个值在所有的机器中必须是唯一的,用于安全释放锁。同时,释放锁的时候,只有key存在并且存储的“my_random_value”值和指定的值一样才执行del命令,此过程通过Lua脚本执行,保证原子性。而且,不采用主从复制机制,使用RedLock算法解决获取锁和释放锁的单点故障问题。 面试官:你刚刚说到RedLock算法,它的原理是什么? 小小白:在Redis的分布式环境中,假设有5个Redis master,这些节点完全互相独立,不存在主从复制或者其他集群协调机制。为了取到锁,客户端执行以下操作: 获取当前Unix时间,以毫秒为单位;依次尝试从N个实例,使用相同的key和随机值获取锁。在步骤2,当向Redis设置锁时,客户端应该设置一个网络连接和响应超时时间,这个超时时间应该小于锁的失效时间。例如你的锁自动失效时间为10秒,则超时时间应该在5-50毫秒之间。这样可以避免服务器端Redis已经挂掉的情况下,客户端还在死死地等待响应结果。如果服务器端没有在规定时间内响应,客户端应该尽快尝试另外一个Redis实例;客户端使用当前时间减去开始获取锁时间(步骤1记录的时间)就得到获取锁使用的时间。当且仅当从大多数(这里是3个节点)的Redis节点都取到锁,并且使用的时间小于锁失效时间时,锁才算获取成功。如果取到了锁,key的真正有效时间等于有效时间减去获取锁所使用的时间(步骤3计算的结果);如果因为某些原因,获取锁失败(没有在至少N/2+1个Redis实例取到锁或者取锁时间已经超过了有效时间),客户端应该在所有的Redis实例上进行解锁(即便某些Redis实例根本就没有加锁成功)。面试官:你再说一下基于ZooKeeper的实现方式? 小小白:基于ZooKeeper实现分布式锁的步骤如下: 创建一个目录mylock;线程A想获取锁就在mylock目录下创建临时顺序节点;获取mylock目录下所有的子节点,然后获取比自己小的兄弟节点,如果不存在,则说明当前线程顺序号最小,获得锁;线程B获取所有节点,判断自己不是最小节点,设置监听比自己次小的节点;线程A处理完,删除自己的节点,线程B监听到变更事件,判断自己是不是最小的节点,如果是则获得锁。推荐使用apache的开源库Curator,它是一个ZooKeeper客户端,Curator提供的InterProcessMutex是分布式锁的实现,acquire方法用于获取锁,release方法用于释放锁。 面试官:基于ZooKeeper的实现方式有什么优缺点? 小小白:高可用、可重入、阻塞锁特性,可解决失效死锁问题,但是因为需要频繁的创建和删除节点,性能上不如Redis方式。 微信搜索BGM7756,免费获取以下面试资料!

July 6, 2020 · 1 min · jiezi

字节跳动三轮技术面后端研发提前批

声明:本文作者:炼狱的吹笛人 原文链接:https://www.jianshu.com/p/a44f2e25d98d 人在杭州,投的是深圳岗,所以是在牛客网上的视频面试。 1 一面项目相关介绍一个项目为什么考虑使用Spark?使用华为的服务减少了哪些运维工作?你觉得项目中有哪些比较有意思的点?数据处理方面做了哪些工作?用Redis做了什么?使用过Redis的什么命令?什么情况下会用到flush?如果一个信息更新非常频繁会怎么应对? 前面的结合自己的实际经验回答即可。 最后一题答使用了消息队列做缓冲。手写代码 很经典的一个二叉树镜像问题,让我做两个事情:如何将这个问题进行抽象(其实就是算法的思路)实现算法 面试官看完我的代码后进行了追问: Worst case下你的代码的时间和空间复杂度?书本上的问题 面试官也注意到我不是科班出身,答得出来就答打不出来就算了(令人感动>_<+)Windows系统中文件信息是存放在哪里的?双击文件夹时,如何获取里面的信息?了解TCP和UDP吗?各有什么特点?各举一个场景?面试官很和蔼,人超nice的。前面的内容毕竟是自己项目的,答得较有底气;代码题以前也见到过,比较容易就写出来。但是操作系统的问题确实是一问一个懵,好在后面的网络正好前一天复习到。。。 我的提问 后端部门的业务怎么划分?2 二面一面技术后,够了大约十到十五分钟,就进入了二面。这次的难度进行了全面升级。。。 基本情况自我介绍介绍一个项目说一下项目中难点操作系统进程间的通信方式有哪些?哪种效率最高?为什么?内核态在什么时候调用?字节对齐有了解吗?计算机网络UDP最长长度是多少?(此时我回答了不清楚)UDP的包头有什么?包头中有多少个字节用来表示长度?UDP最长长度是多少?从这里可以看出来,面试官的提问很有技巧,通过一步步引导我思考,中间偶尔纠正我的错误,最终能把问题引回到最初。既考察了我的基础知识,也顺带让我学习了一波。 数据结构最大堆有什么特点?构造最大堆的过程?时间复杂度是多少?堆排序的过程?时间复杂度是多少?当时忘记构造二叉堆有坑,完全掉坑里了。。 算法说明如何求斐波那契数列的第N项?为什么你选择迭代而不是递归的方法?怎么求根号N的近似值?要求精度在小数点后5位(我说了二分法并解释了大致思路)你的方法的终止条件是什么?不知道归在哪一类 最近在学习什么?(我回答说地理相关的开源组件,然后没再问下去了)场景实现两个系统,一个机器上有大约1k的小文件,共10G,系统间网络很差,怎么高效地把所有文件从一个系统传送到另一个系统? 这个问题花了很久的时间,我提出自己的实现后,会问我这样实现会有什么问题?还能不能继续优化(网络的硬件层面已经定死了,主要是应用层面怎么优化)?这方面确实不懂,基本只能胡扯,磕磕巴巴说了一些,但是面试官还是听了下去并引导我进行分析,但无奈水平太差提不出什么好点子(掩面哭泣) 手写代码一个角色,从二维矩阵的左上角移动到右下角,每次只能右移或下移,生命值会随着遇到的格子里的数字加减(整数加负数减),到终点变成0就死掉。问初始生命值最少要多少才能安全抵达? 一开始说的是统计所有路径中最后血量的最小值,负数取反加一,正数为0。后来面试官补充说,在中途变成0也会立即死掉,而且在开头变0也会死。我一下子没反应过来思考了一下,面试官就主动降低了难度,说把条件设置成一维,且角色只能右移。虽然后面写出了代码,但他没有评价,大概也不太满意。 我的提问 对技术栈的要求?一面感觉良好,但是二面感觉凉透了。计算机网络一问三不知,系统设计漏洞百出,数据结构踩了坑,算法题还主动被降难度=_=自己作为非科班出身的半路出家码农,确实还有很多需要补充的基础知识和技能。希望以后的面试能吸取经验教训,每次都能比前一次更顺利一点!加油,鹿小葵 更新:没想到二面也通过,收到了预约三面的短信,而三面依旧是技术面。这次得要吸取教训,准备得好一点! 公众号 逆锋起笔 专注分享 Java、Python、前端、大厂经验、职业发展干货;每天下午 14:40 推送,每个程序员值得关注的技术平台。关注即送小编整理的精品视频教程3 三面项目自我介绍项目里的难点或者有趣的地方此处面试官多次提问“难点在哪里呢”,看来有必要好好练习这一块( ° △ °|||)︴ JVM 提问前面试官先问我Java、SpringBoot、MySQL、Redis的熟悉程度,我回答前两项较熟。这里是对着简历问的,可见简历不能瞎写。戏说不是胡说 什么是GC?为什么要GC?GC有哪些算法?什么是垃圾?怎么判断它是垃圾?什么是STW?为什么要STW?会带来什么影响?有没有减少STW时间的方法?Java并发编程什么是线程安全?Java中确保线程安全有什么方法、工具或者容器?(我刚说的)重入锁、倒计数器、循环栅栏等分别是啥?有什么用?在什么情况下使用?了解CopyOnWriteArrayList吗?在什么条件下用它?手写代码把一个中文表示的正整数转成Int,如输入字符串“五千三百万零五百零一”,输出53000501。其中输入的数字小于一亿(且不包括一亿)。 说是先给二十分钟搞出一版,我搞出一版后发现编译不通过还在调,他就直接让我说思路,然后就完了。。。(慌) 其他以后的工作规划(技术面咋问起这来了)提问环节这次运气好,问的专业问题几乎都复习到了,算法题也不算难。但是面试官全程冷漠脸,既不肯定我,也不纠正我,搞得心里很没底。最后说了一句“这次面试先结束了,以后常联系”,不知道是好是坏呢~ 4 后续过了十天左右,收到了offer call和意向书,很开心~由于我面的公司还不算多,不能横向比较,但是字节跳动的面试难度给我的感觉还是挺大的,尤其二面快给我问懵了。面试官喜欢让你讲项目里比较难的或有意思的点,专业知识很注重基础,但不是说背下来就行,需要自己深入去理解的那种;但是相对来说,代码题就比较简单了,只要不被前面的问题吓到,都是能做出来的。 公众号 逆锋起笔 专注分享 Java、Python、前端、大厂经验、职业发展干货;每天下午 14:40 推送,每个程序员值得关注的技术平台。关注即送小编整理的精品视频教程

June 22, 2020 · 1 min · jiezi

你-多久没有跳槽了

对于一份工作,坚持多久跳槽最合适呢?是应该把一份工作至少坚持做满18个月,还是不管自己在这家公司待了多久,一有合适的时机就立刻辞职跳槽呢?原文出处:http://dwz.win/Ep5 临近年关,王丽一直惴惴不安,时刻盯着手机,生怕遗漏任何重要的电话。前不久,她去应聘了一家心仪的单位岗位,过五关斩六将,已经通过了两轮面试。本打算年后辞职的,但左等右等,就是没有等来录取的offer,也没有接到不录用的通知。 思前想后,王丽不知道其中是哪一个环节出错了,就能力而言,她自信完全可以胜任面试的岗位。如果说哪里有薄弱的地方,就是自己每份工作干的时间都不长,最短的9个月,最长的也就2年。而目前的这份工作,也才刚满1年,难道HR是在意这点吗?那究竟工作几年跳槽最合适呢? 有的人认为,如果你真的不喜欢自己的工作,那就应该离开。这是你的生活,你只需要按照自己的规则生活,其他人的规则与你无关。但是,如果一个人在4年内换了3份工作,这会引起CEO或HR的警惕。要么你太容易喜新厌旧,不能持之以恒,要么是因为你绩效不佳被辞退,或者因为你不够忠诚,随时准备跳槽等等,这会对公司团队文化和生产效率造成极大的破坏。这是任何一家企业都不能容忍的,尤其是小型企业。 是应该把一份工作至少坚持做满18个月,还是不管自己在这家公司待了多久,一有合适的时机就立刻辞职跳槽呢?人力资源专家迈克尔·O·切齐表示,这取决于你从工作中学到了多少,以及这份工作对你的职业生涯有何裨益。 8个月内跳槽最糟糕一份工作如果不满8个月就辞职跳槽,这是很糟糕的,除非你能找出非常客观的理由,比如公司大规模的裁员行为或工厂倒闭。 无论是HR还是猎头,对应聘者非常看重的一点便是“忠诚度”,因为一个企业不希望辛辛苦苦培养的员工到头来却为别人做了嫁衣。一个人如果在同一个单位工作年限低于2年往往会被看作“不够忠诚”,不到1年,便被视为“稳定性差”。 8个月内就跳槽,这在HR眼里,或许表明你没有通过6个月的评估或第一个绩效周期。迈克尔建议,你最好在履历中省略这份工作,将任何成就算入自由职业部分。 有些东西太糟糕了,只能被抛弃,其中就包括低于8个月的工作。 18个月是社会公认的下限工作了至少18个月才考虑跳槽,这是社会公认的下限。这意味着你至少安然度过了一个评估周期。通常而言,绩效评估是按年进行的,而且公司只会对工作满 6 个月的员工进行评估。而这正是18个月这个数字的由来。 迈克尔表示,短期工作不能太多,如果你在一份工作中“被诱骗”,工作仅8个月就离职是可以理解的。但如果有5份工作均是如此,这似乎就是你的问题了。除非这份工作非常糟糕,否则你应该至少将这份工作做满18个月,跨越2个日历年。虽然我们不喜欢这些规则,不过许多公司非常不待见前一份工作只干了6至17个月的员工,这是现实。 公众号 逆锋起笔 专注分享 Java、Python、前端、大厂工作经验、职业发展干货,关注即送小编整理的精品编程视频教程;每天下午 14:40 推送,每个程序员值得关注的技术平台。48个月跳槽比较好在其他方面相同的情况下,2年好于18个月,3年好于2年,4年好于3年。3年正是大多数正规企业第一次签合同的期限,如果被公司认可,那么接下来将会是合同续签。工作满4年了,你可以得到在那里工作的“全部学分”,除非有明显的证据证明你表现不佳或停滞不前。如果你有幸在第四或者第五年被内部提拔,那么继续在这个岗位上。 如果到了第四、五年,成绩突出却没有得到更高的职位或者薪水,那么最明智的选择就是跳槽。因为眼下的环境已经成了瓶颈,而且个人的求胜欲望和上进心处于高点,此时跳槽不仅可以得到更高的职位和待遇,也可以继续延续个人的求胜欲望。 72个月还没升迁,赶紧跳工作72个月了,此时,如果你没有得到升职或更好的项目,这份工作将开始给你带来伤害。但是,如果你能不断获得升迁,这份工作可以做多长时间呢?答案是——没有上限。 一个人在进入一个新的工作环境,第一年往往是“打酱油”的熟悉过程;第二年才可能慢慢进入角色,真正融入企业文化;经过前两年的积累,到了第三年才真正出成绩,当然这也是职位和薪资提高的关键时期。工作满四年,除去入职后的第一年,其他三年没有起伏,或者有平级调动,这种情形还是可以接受的。 如果你 6 年之后依旧没有明显的升职记录,这就会让人觉得你胸无大志,虽然你还不至于糟糕到连工作都保不住的程度,但你也只能算是平庸之辈。 感悟在同一个公司同一个职位上,一旦错过了3~5年的跳槽黄金期,员工对安逸的需求大于上进求胜的欲望,随着年龄的增大、家庭琐事的负担,人的惰性将越来越束缚内心,最终沦为朝九晚五混日子的上班族。 公众号 逆锋起笔 专注分享 Java、Python、前端、大厂工作经验、职业发展干货,关注即送小编整理的精品编程视频教程;每天下午 14:40 推送,每个程序员值得关注的技术平台。

June 17, 2020 · 1 min · jiezi

面试系列LazyMan的ES6实现

最近某次笔试看到了一个比较有意思的LazyMan问题,基于自己的一些基础做了一些解答,回来结合了一些相关资料,自己重新代码实现了一遍。 问题描述实现一个LazyMan,可以按照以下方式调用:LazyMan(“Hank”)输出:Hi! This is Hank! LazyMan(“Hank”).sleep(10).eat(“dinner”)输出Hi! This is Hank!//等待10秒..Wake up after 10Eat dinner~ LazyMan(“Hank”).eat(“dinner”).eat(“supper”)输出Hi This is Hank!Eat dinner~Eat supper~ LazyMan(“Hank”).sleepFirst(5).eat(“supper”)输出//等待5秒Wake up after 5Hi This is Hank!Eat supper 以此类推。思路分析看到这个题目,首先注意到一些关键点联想到对应的方案点。 LazyMan(“Hank”)调用,而不是new LazyMan(“Hank”)创建 => 工厂方法返回new对象链式调用实现 => 每次调用返回thissleep需要等待10s => setTimeout实现sleepsetTimeout会放到事件列表中排队,继续执行后面的代码,但是题目中sleep需要阻塞后续操作。 => 考虑将sleep封装成promise,使用async/await等待sleep,实现阻塞。sleepFirst每次在最开始执行,考虑将sleepFirst插入到事件第一个执行。因此,首先我们需要taskQueue记录事件列表,直到调用完成后再执行taskQueue里面的事件。怎么实现调用完成后才开始执行taskQueue的事件呢?答案:setTimeout机制。setTimeout(function(){xxx},0)不是立马执行,这是因为js是单线程的,有一个事件队列机制,setTimeout和setInterval的回调会插入到延迟时间塞入事件队列中,排队执行。 源码展示class _LazyMan { constructor(name) { this.taskQueue = []; this.name = name; this.timer = null; this.sayHi(); } // 每次调用时清楚timer,上一次设置的执行taskQueue就不会运行。 // 重新设置timer,会在下一次调用完后进入执行。 // 当所有调用结束后,就会顺利执行taskQueue队列里的事件 next() { clearTimeout(this.timer); this.timer = setTimeout(async () => { // 执行taskQueue队列里的事件 for (let i = 0; i < this.taskQueue.length; i++) { await this.taskQueue[i](); } }); return this; } sayHi() { this.taskQueue.push(() => { console.log('Hi! This is ' + this.name); }); return this.next(); } eat(str) { this.taskQueue.push(() => { console.log('Eat ' + str); }); return this.next(); } beforSleep(time) { // unshift插入到事件的第一个 this.taskQueue.unshift(() => this.sleepPromise(time)); return this.next(); } sleep(time) { this.taskQueue.push(() => this.sleepPromise(time)); return this.next(); } // sleep的Promise对象,用于给async/await来阻塞后续代码执行 sleepPromise(time) { return new Promise((resolve, reject) => { setTimeout(() => { console.log('wake up after ' + time); resolve(); }, time * 1000); }); }}function LazyMan(name) { return new _LazyMan(name);}调用测试:LazyMan('Herry').beforSleep(1).eat('dinner').sleep(2).eat('check');输出: ...

June 17, 2020 · 1 min · jiezi

分布式服务接口的幂等性如何设计

面试题分布式服务接口的幂等性如何设计(比如不能重复扣款)? 面试官心理分析从这个问题开始,面试官就已经进入了实际的生产问题的面试了。 一个分布式系统中的某个接口,该如何保证幂等性?这个事儿其实是你做分布式系统的时候必须要考虑的一个生产环境的技术问题。啥意思呢? 你看,假如你有个服务提供一些接口供外部调用,这个服务部署在了 5 台机器上,接着有个接口就是付款接口。然后人家用户在前端上操作的时候,不知道为啥,总之就是一个订单不小心发起了两次支付请求,然后这俩请求分散在了这个服务部署的不同的机器上,好了,结果一个订单扣款扣两次。 或者是订单系统调用支付系统进行支付,结果不小心因为网络超时了,然后订单系统走了前面我们看到的那个重试机制,咔嚓给你重试了一把,好,支付系统收到一个支付请求两次,而且因为负载均衡算法落在了不同的机器上,尴尬了。。。 所以你肯定得知道这事儿,否则你做出来的分布式系统恐怕容易埋坑。 面试题剖析这个不是技术问题,这个没有通用的一个方法,这个应该结合业务来保证幂等性。 所谓幂等性,就是说一个接口,多次发起同一个请求,你这个接口得保证结果是准确的,比如不能多扣款、不能多插入一条数据、不能将统计值多加了 1。这就是幂等性。 其实保证幂等性主要是三点: 对于每个请求必须有一个唯一的标识,举个栗子:订单支付请求,肯定得包含订单 id,一个订单 id 最多支付一次,对吧。每次处理完请求之后,必须有一个记录标识这个请求处理过了。常见的方案是在 mysql 中记录个状态啥的,比如支付之前记录一条这个订单的支付流水。每次接收请求需要进行判断,判断之前是否处理过。比如说,如果有一个订单已经支付了,就已经有了一条支付流水,那么如果重复发送这个请求,则此时先插入支付流水,orderId 已经存在了,唯一键约束生效,报错插入不进去的。然后你就不用再扣款了。实际运作过程中,你要结合自己的业务来,比如说利用 redis,用 orderId 作为唯一键。只有成功插入这个支付流水,才可以执行实际的支付扣款。 要求是支付一个订单,必须插入一条支付流水,order_id 建一个唯一键 unique key。你在支付一个订单之前,先插入一条支付流水,order_id 就已经进去了。你就可以写一个标识到 redis 里面去,set order_id payed,下一次重复请求过来了,先查 redis 的 order_id 对应的 value,如果是 payed 就说明已经支付过了,你就别重复支付了。 关注我的微信公众号,第一时间获得我的博客的更新提醒,更有惊喜等着你哟~扫一扫下方二维码或搜索微信号shenshan_laoyuan关注 本篇文章由一文多发平台ArtiPub自动发布

June 10, 2020 · 1 min · jiezi

如何基于-Dubbo-进行服务治理

面试题如何基于 dubbo 进行服务治理、服务降级、失败重试以及超时重试? 面试官心理分析服务治理,这个问题如果问你,其实就是看看你有没有服务治理的思想,因为这个是做过复杂微服务的人肯定会遇到的一个问题。 服务降级,这个是涉及到复杂分布式系统中必备的一个话题,因为分布式系统互相来回调用,任何一个系统故障了,你不降级,直接就全盘崩溃?那就太坑爹了吧。 失败重试,分布式系统中网络请求如此频繁,要是因为网络问题不小心失败了一次,是不是要重试? 超时重试,跟上面一样,如果不小心网络慢一点,超时了,如何重试? 面试题剖析服务治理1. 调用链路自动生成一个大型的分布式系统,或者说是用现在流行的微服务架构来说吧,分布式系统由大量的服务组成。那么这些服务之间互相是如何调用的?调用链路是啥?说实话,几乎到后面没人搞的清楚了,因为服务实在太多了,可能几百个甚至几千个服务。 那就需要基于 dubbo 做的分布式系统中,对各个服务之间的调用自动记录下来,然后自动将各个服务之间的依赖关系和调用链路生成出来,做成一张图,显示出来,大家才可以看到对吧。 2. 服务访问压力以及时长统计需要自动统计各个接口和服务之间的调用次数以及访问延时,而且要分成两个级别。 一个级别是接口粒度,就是每个服务的每个接口每天被调用多少次,TP50/TP90/TP99,三个档次的请求延时分别是多少;第二个级别是从源头入口开始,一个完整的请求链路经过几十个服务之后,完成一次请求,每天全链路走多少次,全链路请求延时的 TP50/TP90/TP99,分别是多少。这些东西都搞定了之后,后面才可以来看当前系统的压力主要在哪里,如何来扩容和优化啊。 3. 其它服务分层(避免循环依赖)调用链路失败监控和报警服务鉴权每个服务的可用性的监控(接口调用成功率?几个 9?99.99%,99.9%,99%)服务降级比如说服务 A 调用服务 B,结果服务 B 挂掉了,服务 A 重试几次调用服务 B,还是不行,那么直接降级,走一个备用的逻辑,给用户返回响应。 举个栗子,我们有接口 HelloService。HelloServiceImpl 有该接口的具体实现。 public interface HelloService { void sayHello();}public class HelloServiceImpl implements HelloService { public void sayHello() { System.out.println("hello world......"); }}<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <dubbo:application name="dubbo-provider" /> <dubbo:registry address="zookeeper://127.0.0.1:2181" /> <dubbo:protocol name="dubbo" port="20880" /> <dubbo:service interface="com.zhss.service.HelloService" ref="helloServiceImpl" timeout="10000" /> <bean id="helloServiceImpl" class="com.zhss.service.HelloServiceImpl" /></beans><?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <dubbo:application name="dubbo-consumer" /> <dubbo:registry address="zookeeper://127.0.0.1:2181" /> <dubbo:reference id="fooService" interface="com.test.service.FooService" timeout="10000" check="false" mock="return null"> </dubbo:reference></beans>我们调用接口失败的时候,可以通过 mock 统一返回 null。 ...

June 10, 2020 · 1 min · jiezi

Dubbo-的-spi-思想是什么

面试题dubbo 的 spi 思想是什么? 面试官心理分析继续深入问呗,前面一些基础性的东西问完了,确定你应该都 ok,了解 dubbo 的一些基本东西,那么问个稍微难一点点的问题,就是 spi,先问问你 spi 是啥?然后问问你 dubbo 的 spi 是怎么实现的? 其实就是看看你对 dubbo 的掌握如何。 面试题剖析spi 是啥?spi,简单来说,就是 service provider interface,说白了是什么意思呢,比如你有个接口,现在这个接口有 3 个实现类,那么在系统运行的时候对这个接口到底选择哪个实现类呢?这就需要 spi 了,需要根据指定的配置或者是默认的配置,去找到对应的实现类加载进来,然后用这个实现类的实例对象。 举个栗子。 你有一个接口 A。A1/A2/A3 分别是接口A的不同实现。你通过配置 接口 A = 实现 A2,那么在系统实际运行的时候,会加载你的配置,用实现 A2 实例化一个对象来提供服务。 spi 机制一般用在哪儿?插件扩展的场景,比如说你开发了一个给别人使用的开源框架,如果你想让别人自己写个插件,插到你的开源框架里面,从而扩展某个功能,这个时候 spi 思想就用上了。 Java spi 思想的体现spi 经典的思想体现,大家平时都在用,比如说 jdbc。 Java 定义了一套 jdbc 的接口,但是 Java 并没有提供 jdbc 的实现类。 但是实际上项目跑的时候,要使用 jdbc 接口的哪些实现类呢?一般来说,我们要根据自己使用的数据库,比如 mysql,你就将 mysql-jdbc-connector.jar 引入进来;oracle,你就将 oracle-jdbc-connector.jar 引入进来。 在系统跑的时候,碰到你使用 jdbc 的接口,他会在底层使用你引入的那个 jar 中提供的实现类。 ...

June 10, 2020 · 2 min · jiezi

Dubbo-负载均衡策略和集群容错策略

面试题dubbo 负载均衡策略和集群容错策略都有哪些?动态代理策略呢? 面试官心理分析继续深问吧,这些都是用 dubbo 必须知道的一些东西,你得知道基本原理,知道序列化是什么协议,还得知道具体用 dubbo 的时候,如何负载均衡,如何高可用,如何动态代理。 说白了,就是看你对 dubbo 熟悉不熟悉: dubbo 工作原理:服务注册、注册中心、消费者、代理通信、负载均衡;网络通信、序列化:dubbo 协议、长连接、NIO、hessian 序列化协议;负载均衡策略、集群容错策略、动态代理策略:dubbo 跑起来的时候一些功能是如何运转的?怎么做负载均衡?怎么做集群容错?怎么生成动态代理?dubbo SPI 机制:你了解不了解 dubbo 的 SPI 机制?如何基于 SPI 机制对 dubbo 进行扩展?面试题剖析dubbo 负载均衡策略random loadbalance默认情况下,dubbo 是 random load balance ,即随机调用实现负载均衡,可以对 provider 不同实例设置不同的权重,会按照权重来负载均衡,权重越大分配流量越高,一般就用这个默认的就可以了。 roundrobin loadbalance这个的话默认就是均匀地将流量打到各个机器上去,但是如果各个机器的性能不一样,容易导致性能差的机器负载过高。所以此时需要调整权重,让性能差的机器承载权重小一些,流量少一些。 举个栗子。 跟运维同学申请机器,有的时候,我们运气好,正好公司资源比较充足,刚刚有一批热气腾腾、刚刚做好的虚拟机新鲜出炉,配置都比较高:8 核 + 16G 机器,申请到 2 台。过了一段时间,我们感觉 2 台机器有点不太够,我就去找运维同学说,“哥儿们,你能不能再给我一台机器”,但是这时只剩下一台 4 核 + 8G 的机器。我要还是得要。 这个时候,可以给两台 8 核 16G 的机器设置权重 4,给剩余 1 台 4 核 8G 的机器设置权重 2。 leastactive loadbalance这个就是自动感知一下,如果某个机器性能越差,那么接收的请求越少,越不活跃,此时就会给不活跃的性能差的机器更少的请求。 ...

June 9, 2020 · 1 min · jiezi

说一下-Dubbo-的工作原理

面试题说一下的 dubbo 的工作原理?注册中心挂了可以继续通信吗?说说一次 rpc 请求的流程? 面试官心理分析MQ、ES、Redis、Dubbo,上来先问你一些思考性的问题、原理,比如 kafka 高可用架构原理、es 分布式架构原理、redis 线程模型原理、Dubbo 工作原理;之后就是生产环境里可能会碰到的一些问题,因为每种技术引入之后生产环境都可能会碰到一些问题;再来点综合的,就是系统设计,比如让你设计一个 MQ、设计一个搜索引擎、设计一个缓存、设计一个 rpc 框架等等。 那既然开始聊分布式系统了,自然重点先聊聊 dubbo 了,毕竟 dubbo 是目前事实上大部分公司的分布式系统的 rpc 框架标准,基于 dubbo 也可以构建一整套的微服务架构。但是需要自己大量开发。 当然去年开始 spring cloud 非常火,现在大量的公司开始转向 spring cloud 了,spring cloud 人家毕竟是微服务架构的全家桶式的这么一个东西。但是因为很多公司还在用 dubbo,所以 dubbo 肯定会是目前面试的重点,何况人家 dubbo 现在重启开源社区维护了,捐献给了 apache,未来应该也还是有一定市场和地位的。 既然聊 dubbo,那肯定是先从 dubbo 原理开始聊了,你先说说 dubbo 支撑 rpc 分布式调用的架构啥的,然后说说一次 rpc 请求 dubbo 是怎么给你完成的,对吧。 面试题剖析dubbo 工作原理第一层:service 层,接口层,给服务提供者和消费者来实现的第二层:config 层,配置层,主要是对 dubbo 进行各种配置的第三层:proxy 层,服务代理层,无论是 consumer 还是 provider,dubbo 都会给你生成代理,代理之间进行网络通信第四层:registry 层,服务注册层,负责服务的注册与发现第五层:cluster 层,集群层,封装多个服务提供者的路由以及负载均衡,将多个实例组合成一个服务第六层:monitor 层,监控层,对 rpc 接口的调用次数和调用时间进行监控第七层:protocal 层,远程调用层,封装 rpc 调用第八层:exchange 层,信息交换层,封装请求响应模式,同步转异步第九层:transport 层,网络传输层,抽象 mina 和 netty 为统一接口第十层:serialize 层,数据序列化层工作流程第一步:provider 向注册中心去注册第二步:consumer 从注册中心订阅服务,注册中心会通知 consumer 注册好的服务第三步:consumer 调用 provider第四步:consumer 和 provider 都异步通知监控中心 ...

June 5, 2020 · 1 min · jiezi

Dubbo-支持哪些序列化协议

面试题dubbo 支持哪些通信协议?支持哪些序列化协议?说一下 Hessian 的数据结构?PB 知道吗?为什么 PB 的效率是最高的? 面试官心理分析上一个问题,说说 dubbo 的基本工作原理,那是你必须知道的,至少要知道 dubbo 分成哪些层,然后平时怎么发起 rpc 请求的,注册、发现、调用,这些是基本的。 接着就可以针对底层进行深入的问问了,比如第一步就可以先问问序列化协议这块,就是平时 RPC 的时候怎么走的? 面试题剖析序列化,就是把数据结构或者是一些对象,转换为二进制串的过程,而反序列化是将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程。 dubbo 支持不同的通信协议dubbo 协议默认就是走 dubbo 协议,单一长连接,进行的是 NIO 异步通信,基于 hessian 作为序列化协议。使用的场景是:传输数据量小(每次请求在 100kb 以内),但是并发量很高。 为了要支持高并发场景,一般是服务提供者就几台机器,但是服务消费者有上百台,可能每天调用量达到上亿次!此时用长连接是最合适的,就是跟每个服务消费者维持一个长连接就可以,可能总共就 100 个连接。然后后面直接基于长连接 NIO 异步通信,可以支撑高并发请求。 长连接,通俗点说,就是建立连接过后可以持续发送请求,无须再建立连接。 而短连接,每次要发送请求之前,需要先重新建立一次连接。 rmi 协议走 Java 二进制序列化,多个短连接,适合消费者和提供者数量差不多的情况,适用于文件的传输,一般较少用。 hessian 协议走 hessian 序列化协议,多个短连接,适用于提供者数量比消费者数量还多的情况,适用于文件的传输,一般较少用。 http 协议走 json 序列化。 webservice走 SOAP 文本序列化。 dubbo 支持的序列化协议dubbo 支持 hession、Java 二进制序列化、json、SOAP 文本序列化多种序列化协议。但是 hessian 是其默认的序列化协议。 说一下 Hessian 的数据结构Hessian 的对象序列化机制有 8 种原始类型: ...

June 5, 2020 · 1 min · jiezi

面试常挂题你最大的缺点是什么

这个问题看起来确实不太好回答,好像是在给自己挖坑,说什么都不好。 网上有很多答案: 我最大的缺点就是没有缺点;我是个工作狂;我追求极致,一定要把工作做好。。这也太假了吧,面试官也是从面试者过来的,他也都上网查过知道这些答案,难道问出来是想听一个网上的答案吗? 破解之道所有的面试问题的破解之道都在于换位思考,即:如果你是面试官,你想通过这题问什么?看出来什么? 退一步来想,你是如何知道自己的缺点的呢? 古人有云: 吾日三省吾身: 为人谋而不忠乎? 与朋友交而不信乎? 传不习乎?没错,就是这句我们从小学语文就在背诵的子曰,直到三十而立的面试还会被问。 而我们是否在每天的忙碌中忘了「省吾身」呢? 这题考察的就是一个人是否能正确的「反省」自己,知道自己的优势和劣势,并加以改正和提高。 只回答出自己的缺点是不够的,反省的目的是为了克服缺点、提高自己,所以完整的答案是包含以上两方面的。 避坑但是呢,面试毕竟是面试,有些大实话,还是不说的好: 我这个人就是懒,拖延;我总是能 miss ddl,领导交给我的任务完不成;我这人技术不太行。。。参考答案其实在每个人的不同阶段,都应该有不同的答案,而这个答案一定是你认真的反省自己所得到的,这样才能有理有据,首先把自己说服了,才能让面试官信服。 比如我刚毕业的时候就会说,自己的实战经验少。虽然理论在学校学了很多,但是项目经验可能还不足,自己有在学校/课外做的项目来弥补,但是想必和大公司中的项目无论从规模还是技术上都差很多,所以想进大公司多多学习,您能跟我介绍下你们组现在在做的项目吗? 这个回答, 一来是显示了自己扎实的理论基础。公司是如何衡量一个人的发展潜力的? 就像市场一样,从历史预测未来。 人生不会是大的随机过程,而是一个回归分析。 历史做得好,不见得未来一定做得好;但是大概率是可以做的好的。 历史做得不好,拿什么让别人相信你未来能做好呢? 哪怕我工作一年之后再申请 Citadel 的时候,猎头都跟我说要求 GPA 多少以上。 项目经验不足是实话,学生做的项目就是和工业界的标准不一样,所以这个缺点是客观存在的,无可厚非的。但是我也有去克服呀:展示自己曾经做过的项目,如果面试官有兴趣,我会详细说一下自己做的和面试职位相关的项目。最后抛出问题,和面试官「聊」起来。如果他愿意和你说,那这个问题就成功了。面试中的问题不可能全都提前准备好、背好答案,只有平时就多想多思考,面试才是一个你日常工作生活的缩影,而不是一场表演。演得了一时,演不了一世,即便表演通过了,之后只会有无尽的痛苦。 比如每次发文后我会根据数据和读者的反馈进行反思,并调整之后的内容,你是否发现了呢? 面试中有哪些常见的非技术问题?公众号后台回复「BQ」二字,送你常考题列表~

June 2, 2020 · 1 min · jiezi

写着写着代码就被拷上了警车

1. 事件回顾事件一,2020 年 5 月 26 日发生的利用互联网技术进行违法犯罪活动的破获现场,该事件就发生在我身边。 事件二,某公司暴雷现场,墙上的标语让人深思。 时间三,2020 年 5 月 18 日发生在深圳某某互联公司的抓捕现场。 近年来利用互联网进行犯罪活动持续高发,甚至出现了一些新闻热点事件。作为一名程序员应该加强警惕,提高法律意识,避免被不良公司蒙骗。从上面一系列的事件中我们可以发现很多都是年轻人,在大好时光发生这种事情让人感到十分可惜。 以上案例均来自权威媒体,欢迎对号入座。2. 法律后果如果卷入了这种案件,代价是十分严重的。 承担相应的法律责任,有可能罚没个人财产和失去人身自由。影响个人声誉。工资可能打水漂了。降低个人的竞争力,没有企业喜欢一个有“案底”的人。无法从事某些行业岗位,比如公务员和教师。子女也会受到一些潜在的影响,比如政审,也会影响子女的心里健康。就上面的事件在微信群传播后,一些同学还不以为然,认为自己只是写代码的并没有直接参与违法活动。这种观点是错误的,也是可怕的。首先相关的需求程序员肯定参与了不可能不知晓,一旦涉嫌刑事犯罪就肯定构成了主观故意和放任的主观要件。虽然有可能免于处罚,那是因为情节轻微不够刑事处罚或者免于刑事处罚。而这种判定具有一定的主观性,决定权不在你自己。 所以我们不能不重视这个问题,不能成为违法犯罪的帮凶。 那么该如何规避这些风险呢? 3. 程序员如何规避风险结合我历年来找工作的经验来总结一些“避坑”的经验: 通过正规招聘渠道找工作,不要通过一些黑中介、黑猎头,东南亚杀猪盘的事情相信知道的不少了吧。首先要对你心仪的公司进行背调,查相关的财务状况、从事的行业、是否有重大的违法违规记录、社会风评。避开一些高危行业。比如可能搞套路贷金融的、非法使用爬虫取公民个人信息的、搞色情直播的、搞互联网黑产的、打着区块链的幌子搞非法集资的、搞非法游戏进行敛财的等等对于特别容易面试成功、工资高于地区水平很多职位的也要留一个心眼。对于一些有可能违法犯罪的需求要懂得拒绝,不用管他职务多大,但是注意个人安全,注意拒绝方式。平时也要对国家在互联网、计算机行业内相关法律法规进行学习了解,做到知法守法。4. 总结无数个案例在警示着我们,甚至就发生在你我身边。所以万事安全第一,远离那些不正当的公司,不做违法犯罪的需求,拒绝面向“监狱”编程。 关注公众号:Felordcn 获取更多资讯 个人博客:https://felord.cn

May 31, 2020 · 1 min · jiezi

为什么要进行系统拆分

面试题为什么要进行系统拆分?如何进行系统拆分?拆分后不用 dubbo 可以吗? 面试官心理分析从这个问题开始就进行分布式系统环节了,现在出去面试分布式都成标配了,没有哪个公司不问问你分布式的事儿。你要是不会分布式的东西,简直这简历没法看,没人会让你去面试。 其实为啥会这样呢?这就是因为整个大行业技术发展的原因。 早些年,印象中在 2010 年初的时候,整个 IT 行业,很少有人谈分布式,更不用说微服务,虽然很多 BAT 等大型公司,因为系统的复杂性,很早就是分布式架构,大量的服务,只不过微服务大多基于自己搞的一套框架来实现而已。 但是确实,那个年代,大家很重视 ssh2,很多中小型公司几乎大部分都是玩儿 struts2、spring、hibernate,稍晚一些,才进入了 spring mvc、spring、mybatis 的组合。那个时候整个行业的技术水平就是那样,当年 oracle 很火,oracle 管理员很吃香,oracle 性能优化啥的都是 IT 男的大杀招啊。连大数据都没人提,当年 OCP、OCM 等认证培训机构,火的不行。 但是确实随着时代的发展,慢慢的,很多公司开始接受分布式系统架构了,这里面尤为对行业有至关重要影响的,是阿里的 dubbo,某种程度上而言,阿里在这里推动了行业技术的前进。 正是因为有阿里的 dubbo,很多中小型公司才可以基于 dubbo,来把系统拆分成很多的服务,每个人负责一个服务,大家的代码都没有冲突,服务可以自治,自己选用什么技术都可以,每次发布如果就改动一个服务那就上线一个服务好了,不用所有人一起联调,每次发布都是几十万行代码,甚至几百万行代码了。 直到今日,很高兴看到分布式系统都成行业面试标配了,任何一个普通的程序员都该掌握这个东西,其实这是行业的进步,也是所有 IT 码农的技术进步。所以既然分布式都成标配了,那么面试官当然会问了,因为很多公司现在都是分布式、微服务的架构,那面试官当然得考察考察你了。 面试题剖析为什么要将系统进行拆分?网上查查,答案极度零散和复杂,很琐碎,原因一大坨。但是我这里给大家直观的感受: 要是不拆分,一个大系统几十万行代码,20 个人维护一份代码,简直是悲剧啊。代码经常改着改着就冲突了,各种代码冲突和合并要处理,非常耗费时间;经常我改动了我的代码,你调用了我的,导致你的代码也得重新测试,麻烦的要死;然后每次发布都是几十万行代码的系统一起发布,大家得一起提心吊胆准备上线,几十万行代码的上线,可能每次上线都要做很多的检查,很多异常问题的处理,简直是又麻烦又痛苦;而且如果我现在打算把技术升级到最新的 spring 版本,还不行,因为这可能导致你的代码报错,我不敢随意乱改技术。 假设一个系统是 20 万行代码,其中 A 在里面改了 1000 行代码,但是此时发布的时候是这个 20 万行代码的大系统一块儿发布。就意味着 20 万上代码在线上就可能出现各种变化,20 个人,每个人都要紧张地等在电脑面前,上线之后,检查日志,看自己负责的那一块儿有没有什么问题。 A 就检查了自己负责的 1 万行代码对应的功能,确保 ok 就闪人了;结果不巧的是,A 上线的时候不小心修改了线上机器的某个配置,导致另外 B 和 C 负责的 2 万行代码对应的一些功能,出错了。 几十个人负责维护一个几十万行代码的单块应用,每次上线,准备几个礼拜,上线 -> 部署 -> 检查自己负责的功能。 ...

May 28, 2020 · 1 min · jiezi

如何设计一个高并发系统

面试题如何设计一个高并发系统? 面试官心理分析说实话,如果面试官问你这个题目,那么你必须要使出全身吃奶劲了。为啥?因为你没看到现在很多公司招聘的 JD 里都是说啥,有高并发就经验者优先。 如果你确实有真才实学,在互联网公司里干过高并发系统,那你确实拿 offer 基本如探囊取物,没啥问题。面试官也绝对不会这样来问你,否则他就是蠢。 假设你在某知名电商公司干过高并发系统,用户上亿,一天流量几十亿,高峰期并发量上万,甚至是十万。那么人家一定会仔细盘问你的系统架构,你们系统啥架构?怎么部署的?部署了多少台机器?缓存咋用的?MQ 咋用的?数据库咋用的?就是深挖你到底是如何扛住高并发的。 因为真正干过高并发的人一定知道,脱离了业务的系统架构都是在纸上谈兵,真正在复杂业务场景而且还高并发的时候,那系统架构一定不是那么简单的,用个 redis,用 mq 就能搞定?当然不是,真实的系统架构搭配上业务之后,会比这种简单的所谓“高并发架构”要复杂很多倍。 如果有面试官问你个问题说,如何设计一个高并发系统?那么不好意思,一定是因为你实际上没干过高并发系统。面试官看你简历就没啥出彩的,感觉就不咋地,所以就会问问你,如何设计一个高并发系统?其实说白了本质就是看看你有没有自己研究过,有没有一定的知识积累。 最好的当然是招聘个真正干过高并发的哥儿们咯,但是这种哥儿们人数稀缺,不好招。所以可能次一点的就是招一个自己研究过的哥儿们,总比招一个啥也不会的哥儿们好吧! 所以这个时候你必须得做一把个人秀了,秀出你所有关于高并发的知识! 面试题剖析其实所谓的高并发,如果你要理解这个问题呢,其实就得从高并发的根源出发,为啥会有高并发?为啥高并发就很牛逼? 我说的浅显一点,很简单,就是因为刚开始系统都是连接数据库的,但是要知道数据库支撑到每秒并发两三千的时候,基本就快完了。所以才有说,很多公司,刚开始干的时候,技术比较 low,结果业务发展太快,有的时候系统扛不住压力就挂了。 当然会挂了,凭什么不挂?你数据库如果瞬间承载每秒 5000/8000,甚至上万的并发,一定会宕机,因为比如 mysql 就压根儿扛不住这么高的并发量。 所以为啥高并发牛逼?就是因为现在用互联网的人越来越多,很多 app、网站、系统承载的都是高并发请求,可能高峰期每秒并发量几千,很正常的。如果是什么双十一之类的,每秒并发几万几十万都有可能。 那么如此之高的并发量,加上原本就如此之复杂的业务,咋玩儿?真正厉害的,一定是在复杂业务系统里玩儿过高并发架构的人,但是你没有,那么我给你说一下你该怎么回答这个问题: 可以分为以下 6 点: 系统拆分缓存MQ分库分表读写分离ElasticSearch 系统拆分将一个系统拆分为多个子系统,用 dubbo 来搞。然后每个系统连一个数据库,这样本来就一个库,现在多个数据库,不也可以扛高并发么。 缓存缓存,必须得用缓存。大部分的高并发场景,都是读多写少,那你完全可以在数据库和缓存里都写一份,然后读的时候大量走缓存不就得了。毕竟人家 redis 轻轻松松单机几万的并发。所以你可以考虑考虑你的项目里,那些承载主要请求的读场景,怎么用缓存来抗高并发。 MQMQ,必须得用 MQ。可能你还是会出现高并发写的场景,比如说一个业务操作里要频繁搞数据库几十次,增删改增删改,疯了。那高并发绝对搞挂你的系统,你要是用 redis 来承载写那肯定不行,人家是缓存,数据随时就被 LRU 了,数据格式还无比简单,没有事务支持。所以该用 mysql 还得用 mysql 啊。那你咋办?用 MQ 吧,大量的写请求灌入 MQ 里,排队慢慢玩儿,后边系统消费后慢慢写,控制在 mysql 承载范围之内。所以你得考虑考虑你的项目里,那些承载复杂写业务逻辑的场景里,如何用 MQ 来异步写,提升并发性。MQ 单机抗几万并发也是 ok 的,这个之前还特意说过。 分库分表分库分表,可能到了最后数据库层面还是免不了抗高并发的要求,好吧,那么就将一个数据库拆分为多个库,多个库来扛更高的并发;然后将一个表拆分为多个表,每个表的数据量保持少一点,提高 sql 跑的性能。 读写分离读写分离,这个就是说大部分时候数据库可能也是读多写少,没必要所有请求都集中在一个库上吧,可以搞个主从架构,主库写入,从库读取,搞一个读写分离。读流量太多的时候,还可以加更多的从库。 ElasticSearchElasticsearch,简称 es。es 是分布式的,可以随便扩容,分布式天然就可以支撑高并发,因为动不动就可以扩容加机器来扛更高的并发。那么一些比较简单的查询、统计类的操作,可以考虑用 es 来承载,还有一些全文搜索类的操作,也可以考虑用 es 来承载。 ...

May 28, 2020 · 1 min · jiezi

分库分表之后id-主键如何处理

面试题分库分表之后,id 主键如何处理? 面试官心理分析其实这是分库分表之后你必然要面对的一个问题,就是 id 咋生成?因为要是分成多个表之后,每个表都是从 1 开始累加,那肯定不对啊,需要一个全局唯一的 id 来支持。所以这都是你实际生产环境中必须考虑的问题。 面试题剖析基于数据库的实现方案数据库自增 id这个就是说你的系统里每次得到一个 id,都是往一个库的一个表里插入一条没什么业务含义的数据,然后获取一个数据库自增的一个 id。拿到这个 id 之后再往对应的分库分表里去写入。 这个方案的好处就是方便简单,谁都会用;缺点就是单库生成自增 id,要是高并发的话,就会有瓶颈的;如果你硬是要改进一下,那么就专门开一个服务出来,这个服务每次就拿到当前 id 最大值,然后自己递增几个 id,一次性返回一批 id,然后再把当前最大 id 值修改成递增几个 id 之后的一个值;但是无论如何都是基于单个数据库。 适合的场景:你分库分表就俩原因,要不就是单库并发太高,要不就是单库数据量太大;除非是你并发不高,但是数据量太大导致的分库分表扩容,你可以用这个方案,因为可能每秒最高并发最多就几百,那么就走单独的一个库和表生成自增主键即可。 设置数据库 sequence 或者表自增字段步长可以通过设置数据库 sequence 或者表的自增字段步长来进行水平伸缩。 比如说,现在有 8 个服务节点,每个服务节点使用一个 sequence 功能来产生 ID,每个 sequence 的起始 ID 不同,并且依次递增,步长都是 8。 适合的场景:在用户防止产生的 ID 重复时,这种方案实现起来比较简单,也能达到性能目标。但是服务节点固定,步长也固定,将来如果还要增加服务节点,就不好搞了。 UUID好处就是本地生成,不要基于数据库来了;不好之处就是,UUID 太长了、占用空间大,作为主键性能太差了;更重要的是,UUID 不具有有序性,会导致 B+ 树索引在写的时候有过多的随机写操作(连续的 ID 可以产生部分顺序写),还有,由于在写的时候不能产生有顺序的 append 操作,而需要进行 insert 操作,将会读取整个 B+ 树节点到内存,在插入这条记录后会将整个节点写回磁盘,这种操作在记录占用空间比较大的情况下,性能下降明显。 适合的场景:如果你是要随机生成个什么文件名、编号之类的,你可以用 UUID,但是作为主键是不能用 UUID 的。 UUID.randomUUID().toString().replace("-", "") -> sfsdf23423rr234sfdaf获取系统当前时间这个就是获取当前时间即可,但是问题是,并发很高的时候,比如一秒并发几千,会有重复的情况,这个是肯定不合适的。基本就不用考虑了。 ...

May 28, 2020 · 3 min · jiezi

分库分表如何平滑过渡

面试题现在有一个未分库分表的系统,未来要分库分表,如何设计才可以让系统从未分库分表动态切换到分库分表上? 面试官心理分析你看看,你现在已经明白为啥要分库分表了,你也知道常用的分库分表中间件了,你也设计好你们如何分库分表的方案了(水平拆分、垂直拆分、分表),那问题来了,你接下来该怎么把你那个单库单表的系统给迁移到分库分表上去? 所以这都是一环扣一环的,就是看你有没有全流程经历过这个过程。 面试题剖析这个其实从 low 到高大上有好几种方案,我们都玩儿过,我都给你说一下。 停机迁移方案我先给你说一个最 low 的方案,就是很简单,大家伙儿凌晨 12 点开始运维,网站或者 app 挂个公告,说 0 点到早上 6 点进行运维,无法访问。 接着到 0 点停机,系统停掉,没有流量写入了,此时老的单库单表数据库静止了。然后你之前得写好一个导数的一次性工具,此时直接跑起来,然后将单库单表的数据哗哗哗读出来,写到分库分表里面去。 导数完了之后,就 ok 了,修改系统的数据库连接配置啥的,包括可能代码和 SQL 也许有修改,那你就用最新的代码,然后直接启动连到新的分库分表上去。 验证一下,ok了,完美,大家伸个懒腰,看看看凌晨 4 点钟的北京夜景,打个滴滴回家吧。 但是这个方案比较 low,谁都能干,我们来看看高大上一点的方案。 双写迁移方案这个是我们常用的一种迁移方案,比较靠谱一些,不用停机,不用看北京凌晨 4 点的风景。 简单来说,就是在线上系统里面,之前所有写库的地方,增删改操作,除了对老库增删改,都加上对新库的增删改,这就是所谓的双写,同时写俩库,老库和新库。 然后系统部署之后,新库数据差太远,用之前说的导数工具,跑起来读老库数据写新库,写的时候要根据 gmt_modified 这类字段判断这条数据最后修改的时间,除非是读出来的数据在新库里没有,或者是比新库的数据新才会写。简单来说,就是不允许用老数据覆盖新数据。 导完一轮之后,有可能数据还是存在不一致,那么就程序自动做一轮校验,比对新老库每个表的每条数据,接着如果有不一样的,就针对那些不一样的,从老库读数据再次写。反复循环,直到两个库每个表的数据都完全一致为止。 接着当数据完全一致了,就 ok 了,基于仅仅使用分库分表的最新代码,重新部署一次,不就仅仅基于分库分表在操作了么,还没有几个小时的停机时间,很稳。所以现在基本玩儿数据迁移之类的,都是这么干的。 关注我的微信公众号,第一时间获得我的博客的更新提醒,更有惊喜等着你哟~扫一扫下方二维码或搜索微信号shenshan_laoyuan关注 本篇文章由一文多发平台ArtiPub自动发布

May 28, 2020 · 1 min · jiezi

如何设计可以动态扩容缩容的分库分表方案

面试题如何设计可以动态扩容缩容的分库分表方案? 面试官心理分析对于分库分表来说,主要是面对以下问题: 选择一个数据库中间件,调研、学习、测试;设计你的分库分表的一个方案,你要分成多少个库,每个库分成多少个表,比如 3 个库,每个库 4 个表;基于选择好的数据库中间件,以及在测试环境建立好的分库分表的环境,然后测试一下能否正常进行分库分表的读写;完成单库单表到分库分表的迁移,双写方案;线上系统开始基于分库分表对外提供服务;扩容了,扩容成 6 个库,每个库需要 12 个表,你怎么来增加更多库和表呢?这个是你必须面对的一个事儿,就是你已经弄好分库分表方案了,然后一堆库和表都建好了,基于分库分表中间件的代码开发啥的都好了,测试都 ok 了,数据能均匀分布到各个库和各个表里去,而且接着你还通过双写的方案咔嚓一下上了系统,已经直接基于分库分表方案在搞了。 那么现在问题来了,你现在这些库和表又支撑不住了,要继续扩容咋办?这个可能就是说你的每个库的容量又快满了,或者是你的表数据量又太大了,也可能是你每个库的写并发太高了,你得继续扩容。 这都是玩儿分库分表线上必须经历的事儿。 面试题剖析停机扩容(不推荐)这个方案就跟停机迁移一样,步骤几乎一致,唯一的一点就是那个导数的工具,是把现有库表的数据抽出来慢慢倒入到新的库和表里去。但是最好别这么玩儿,有点不太靠谱,因为既然分库分表就说明数据量实在是太大了,可能多达几亿条,甚至几十亿,你这么玩儿,可能会出问题。 从单库单表迁移到分库分表的时候,数据量并不是很大,单表最大也就两三千万。那么你写个工具,多弄几台机器并行跑,1小时数据就导完了。这没有问题。 如果 3 个库 + 12 个表,跑了一段时间了,数据量都 1~2 亿了。光是导 2 亿数据,都要导个几个小时,6 点,刚刚导完数据,还要搞后续的修改配置,重启系统,测试验证,10 点才可以搞完。所以不能这么搞。 优化后的方案一开始上来就是 32 个库,每个库 32 个表,那么总共是 1024 张表。 我可以告诉各位同学,这个分法,第一,基本上国内的互联网肯定都是够用了,第二,无论是并发支撑还是数据量支撑都没问题。 每个库正常承载的写入并发量是 1000,那么 32 个库就可以承载 32 1000 = 32000 的写并发,如果每个库承载 1500 的写并发,32 1500 = 48000 的写并发,接近 5 万每秒的写入并发,前面再加一个MQ,削峰,每秒写入 MQ 8 万条数据,每秒消费 5 万条数据。 有些除非是国内排名非常靠前的这些公司,他们的最核心的系统的数据库,可能会出现几百台数据库的这么一个规模,128 个库,256 个库,512 个库。 1024 张表,假设每个表放 500 万数据,在 MySQL 里可以放 50 亿条数据。 ...

May 28, 2020 · 1 min · jiezi

为什么要分库分表

面试题为什么要分库分表(设计高并发系统的时候,数据库层面该如何设计)?用过哪些分库分表中间件?不同的分库分表中间件都有什么优点和缺点?你们具体是如何对数据库如何进行垂直拆分或水平拆分的? 面试官心理分析其实这块肯定是扯到高并发了,因为分库分表一定是为了支撑高并发、数据量大两个问题的。而且现在说实话,尤其是互联网类的公司面试,基本上都会来这么一下,分库分表如此普遍的技术问题,不问实在是不行,而如果你不知道那也实在是说不过去! 面试题剖析为什么要分库分表?(设计高并发系统的时候,数据库层面该如何设计?)说白了,分库分表是两回事儿,大家可别搞混了,可能是光分库不分表,也可能是光分表不分库,都有可能。 我先给大家抛出来一个场景。 假如我们现在是一个小创业公司(或者是一个 BAT 公司刚兴起的一个新部门),现在注册用户就 20 万,每天活跃用户就 1 万,每天单表数据量就 1000,然后高峰期每秒钟并发请求最多就 10 个。我的天,就这种系统,随便找一个有几年工作经验的,然后带几个刚培训出来的,随便干干都可以。 结果没想到我们运气居然这么好,碰上个 CEO 带着我们走上了康庄大道,业务发展迅猛,过了几个月,注册用户数达到了 2000 万!每天活跃用户数 100 万!每天单表数据量 10 万条!高峰期每秒最大请求达到 1000!同时公司还顺带着融资了两轮,进账了几个亿人民币啊!公司估值达到了惊人的几亿美金!这是小独角兽的节奏! 好吧,没事,现在大家感觉压力已经有点大了,为啥呢?因为每天多 10 万条数据,一个月就多 300 万条数据,现在咱们单表已经几百万数据了,马上就破千万了。但是勉强还能撑着。高峰期请求现在是 1000,咱们线上部署了几台机器,负载均衡搞了一下,数据库撑 1000QPS 也还凑合。但是大家现在开始感觉有点担心了,接下来咋整呢...... 再接下来几个月,我的天,CEO 太牛逼了,公司用户数已经达到 1 亿,公司继续融资几十亿人民币啊!公司估值达到了惊人的几十亿美金,成为了国内今年最牛逼的明星创业公司!天,我们太幸运了。 但是我们同时也是不幸的,因为此时每天活跃用户数上千万,每天单表新增数据多达 50 万,目前一个表总数据量都已经达到了两三千万了!扛不住啊!数据库磁盘容量不断消耗掉!高峰期并发达到惊人的 5000~8000!别开玩笑了,哥。我跟你保证,你的系统支撑不到现在,已经挂掉了! 好吧,所以你看到这里差不多就理解分库分表是怎么回事儿了,实际上这是跟着你的公司业务发展走的,你公司业务发展越好,用户就越多,数据量越大,请求量越大,那你单个数据库一定扛不住。 分表比如你单表都几千万数据了,你确定你能扛住么?绝对不行,单表数据量太大,会极大影响你的 sql 执行的性能,到了后面你的 sql 可能就跑的很慢了。一般来说,就以我的经验来看,单表到几百万的时候,性能就会相对差一些了,你就得分表了。 分表是啥意思?就是把一个表的数据放到多个表中,然后查询的时候你就查一个表。比如按照用户 id 来分表,将一个用户的数据就放在一个表中。然后操作的时候你对一个用户就操作那个表就好了。这样可以控制每个表的数据量在可控的范围内,比如每个表就固定在 200 万以内。 分库分库是啥意思?就是你一个库一般我们经验而言,最多支撑到并发 2000,一定要扩容了,而且一个健康的单库并发值你最好保持在每秒 1000 左右,不要太大。那么你可以将一个库的数据拆分到多个库中,访问的时候就访问一个库好了。 这就是所谓的分库分表,为啥要分库分表?你明白了吧。 #分库分表前分库分表后并发支撑情况MySQL 单机部署,扛不住高并发MySQL从单机到多机,能承受的并发增加了多倍磁盘使用情况MySQL 单机磁盘容量几乎撑满拆分为多个库,数据库服务器磁盘使用率大大降低SQL 执行性能单表数据量太大,SQL 越跑越慢单表数据量减少,SQL 执行效率明显提升用过哪些分库分表中间件?不同的分库分表中间件都有什么优点和缺点?这个其实就是看看你了解哪些分库分表的中间件,各个中间件的优缺点是啥?然后你用过哪些分库分表的中间件。 比较常见的包括: CobarTDDLAtlasSharding-jdbcMycatCobar阿里 b2b 团队开发和开源的,属于 proxy 层方案,就是介于应用服务器和数据库服务器之间。应用程序通过 JDBC 驱动访问 Cobar 集群,Cobar 根据 SQL 和分库规则对 SQL 做分解,然后分发到 MySQL 集群不同的数据库实例上执行。早些年还可以用,但是最近几年都没更新了,基本没啥人用,差不多算是被抛弃的状态吧。而且不支持读写分离、存储过程、跨库 join 和分页等操作。 ...

May 28, 2020 · 1 min · jiezi

吊打面试官系列缓存雪崩击穿穿透

你知道的越多,你不知道的越多点赞再看,养成习惯 前言Redis在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在Redis的使用和原理方面对小伙伴们进行360°的刁难。作为一个在互联网公司面一次拿一次offer的面霸(请允许我使用一下夸张的修辞手法),打败了无数竞争对手,每次都只能看到无数落寞的身影失望的离开,略感愧疚,在一个寂寞难耐的夜晚,我痛定思痛,决定开始写《吊打面试官》系列,希望能帮助各位读者以后面试势如破竹,对面试官进行360°的反击,吊打问你的面试官,让一同面试的同僚瞠目结舌,疯狂收割大厂offer! 一点感慨本来都把稿子放到公众号保存了,洗澡的时候想了一下晚上的比赛,觉得还是打开电脑写点东西,跟文章内容没关系,只是一点个人的感慨,不知道多少小伙伴看了昨天SKT VS G2的比赛,又不知道多少小伙伴还记得Faker手抖的那一幕。 不知道你们看了是什么感受,我看到他手抖的时候我内心也抖了,世界赛我支持的都是LPL的队伍,但是我喜欢李哥这个人,那种对胜利的执著,这么多年了那种坚持自己的坚持,这么多利益诱惑在面前却只想要胜利,这样的人我好喜欢啊,我想很多人也喜欢。 可能就像很多网友说的那样,英雄迟暮,但是我觉得他还是有点东西,就像很多人说我们程序员只能吃年轻饭一样,但是如果你坚持自己的坚持,做个腹有诗书气自华的仔,我想最后肯定会得到自己的得到。 好了我也不煽情了,我们开始讲技术吧。 正文上一期吊打系列我们提到了Redis的基础知识,还没看的小伙伴可以回顾一下 《吊打面试官》系列-Redis基础 那提到Redis我相信各位在面试,或者实际开发过程中对缓存雪崩,穿透,击穿也不陌生吧,就算没遇到过但是你肯定听过,那三者到底有什么区别,我们又应该怎么去防止这样的情况发生呢,我们有请下一位受害者。 面试开始一个大腹便便,穿着格子衬衣的中年男子,拿着一个满是划痕的mac向你走来,看着快秃顶的头发,心想着肯定是尼玛顶级架构师吧!但是我们腹有诗书气自华,虚都不虚。 小伙子我看你的简历上写到了Redis,那么我们直接开门见山,直接怼常见的几个大问题,Redis雪崩了解么?帅气迷人的面试官您好,我了解的,目前电商首页以及热点数据都会去做缓存 ,一般缓存都是定时任务去刷新,或者是查不到之后去更新的,定时任务刷新就有一个问题。 举个简单的例子:如果所有首页的Key失效时间都是12小时,中午12点刷新的,我零点有个秒杀活动大量用户涌入,假设当时每秒 6000 个请求,本来缓存在可以扛住每秒 5000 个请求,但是缓存当时所有的Key都失效了。此时 1 秒 6000 个请求全部落数据库,数据库必然扛不住,它会报一下警,真实情况可能DBA都没反应过来就直接挂了。此时,如果没用什么特别的方案来处理这个故障,DBA 很着急,重启数据库,但是数据库立马又被新的流量给打死了。这就是我理解的缓存雪崩。 我刻意看了下我做过的项目感觉再吊的都不允许这么大的QPS直接打DB去,不过没慢SQL加上分库,大表分表可能还还算能顶,但是跟用了Redis的差距还是很大 同一时间大面积失效,那一瞬间Redis跟没有一样,那这个数量级别的请求直接打到数据库几乎是灾难性的,你想想如果打挂的是一个用户服务的库,那其他依赖他的库所有的接口几乎都会报错,如果没做熔断等策略基本上就是瞬间挂一片的节奏,你怎么重启用户都会把你打挂,等你能重启的时候,用户早就睡觉去了,并且对你的产品失去了信心,什么垃圾产品。 面试官摸了摸自己的头发,嗯还不错,那这种情况咋整?你都是怎么去应对的?处理缓存雪崩简单,在批量往Redis存数据的时候,把每个Key的失效时间都加个随机值就好了,这样可以保证数据不会在同一时间大面积失效,我相信,Redis这点流量还是顶得住的。 setRedis(Key,value,time + Math.random() * 10000);如果Redis是集群部署,将热点数据均匀分布在不同的Redis库中也能避免全部失效的问题,不过本渣我在生产环境中操作集群的时候,单个服务都是对应的单个Redis分片,是为了方便数据的管理,但是也同样有了可能会失效这样的弊端,失效时间随机是个好策略。 或者设置热点数据永远不过期,有更新操作就更新缓存就好了(比如运维更新了首页商品,那你刷下缓存就完事了,不要设置过期时间),电商首页的数据也可以用这个操作,保险。 那你了解缓存穿透和击穿么,可以说说他们跟雪崩的区别么?嗯,了解,我先说一下缓存穿透吧,缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,我们数据库的 id 都是1开始自增上去的,如发起为id值为 -1 的数据或 id 为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大,严重会击垮数据库。 小点的单机系统,基本上用postman就能搞死,比如我自己买的阿里云服务 像这种你如果不对参数做校验,数据库id都是大于0的,我一直用小于0的参数去请求你,每次都能绕开Redis直接打到数据库,数据库也查不到,每次都这样,并发高点就容易崩掉了。 至于缓存击穿嘛,这个跟缓存雪崩有点像,但是又有一点不一样,缓存雪崩是因为大面积的缓存失效,打崩了DB,而缓存击穿不同的是缓存击穿是指一个Key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个Key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个完好无损的桶上凿开了一个洞。 面试官露出欣慰的眼光,那他们分别怎么解决缓存穿透我会在接口层增加校验,比如用户鉴权校验,参数做校验,不合法的参数直接代码Return,比如:id 做基础校验,id <=0的直接拦截等。 这里我想提的一点就是,我们在开发程序的时候都要有一颗“不信任”的心,就是不要相信任何调用方,比如你提供了API接口出去,你有这几个参数,那我觉得作为被调用方,任何可能的参数情况都应该被考虑到,做校验,因为你不相信调用你的人,你不知道他会传什么参数给你。 举个简单的例子,你这个接口是分页查询的,但是你没对分页参数的大小做限制,调用的人万一一口气查 Integer.MAX_VALUE 一次请求就要你几秒,多几个并发你不就挂了么?是公司同事调用还好大不了发现了改掉,但是如果是黑客或者竞争对手呢?在你双十一当天就调你这个接口会发生什么,就不用我说了吧。这是之前的Leader跟我说的,我觉得大家也都应该了解下。 从缓存取不到的数据,在数据库中也没有取到,这时也可以将对应Key的Value对写为null、位置错误、稍后重试这样的值具体取啥问产品,或者看具体的场景,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。 这样可以防止攻击用户反复用同一个id暴力攻击,但是我们要知道正常用户是不会在单秒内发起这么多次请求的,那网关层Nginx本渣我也记得有配置项,可以让运维大大对单个IP每秒访问次数超出阈值的IP都拉黑。 那你还有别的办法么?还有我记得Redis还有一个高级用法布隆过滤器(Bloom Filter)这个也能很好的防止缓存穿透的发生,他的原理也很简单就是利用高效的数据结构和算法快速判断出你这个Key是否在数据库中存在,不存在你return就好了,存在你就去查了DB刷新KV再return。 那又有小伙伴说了如果黑客有很多个IP同时发起攻击呢?这点我一直也不是很想得通,但是一般级别的黑客没这么多肉鸡,再者正常级别的Redis集群都能抗住这种级别的访问的,小公司我想他们不会感兴趣的。把系统的高可用做好了,集群还是很能顶的。 缓存击穿的话,设置热点数据永远不过期。或者加上互斥锁就能搞定了 作为暖男,代码我肯定帮你们准备好了 面试结束嗯嗯还不错,三个点都回答得很好,今天也不早了,面试就先到这里,明天你再过来二面我继续问一下你关于Redis集群高可用,主从同步,哨兵等知识点的问题。晕居然还有下一轮面试!(强行下一期的伏笔哈哈)但是为了offer还是得舔,嗯嗯,好的帅气面试官。 能回答得这么全面这么细节还是忍不住点赞 (暗示点赞,每次都看了不点赞,你们想白嫖我么?你们好坏喲,不过我喜欢) ...

November 5, 2019 · 1 min · jiezi

面试完然后为什么就没然后了提升成功率

前言:     大学毕业想找web前端实习岗位却一直没消息?刚刚培训出来信心满满(但是多少有点虚),也是面试很多找不到工作,面试很多公司,一直没结果?这是为什么? 痛点分析:hr来电话,通知去面试,结果连技术都没问就让回去等通知,然后就没然后了。去公司面试,问的技术很多不会,然后就没然后了。去公司面试,老是问到原理,根本不知道如何回答,然后就没然后了。去公司面试,问到是否有真实项目,然后就没然后了。 去公司面试,感觉回答的不错,说给通知,然后就没然后了。去公司面试,很多地方回答不到“点”上,然后就没然后了。  然后...到底问题出在哪里:其实作为技术来说,就算一个10年工作经验的人,问到很多技术方面的问题,他也是回答不上来的,但是为什么他都可以从容应对?其实公司面试web前端岗位,问技术是一方面,还有一部分看临时回复回答。 你的表现一下就被面试官看穿了,根本就是一个无工作经验的人,经验很不足,一个公司花着钱培养一个没有工作经验的人,如果你是老板,你愿意吗?到底...如何解决...怎么样才可以找到工作?我现在该做些什么?现在还是盲目的去找工作?还是停下来,看点东西,学习一下真正的技巧,再去找一下工作,成功大大提高?公司真实面试题:https://www.3mooc.com/front/c... vue面试题:https://www.3mooc.com/front/c...  送web前端面试题教材,包含:  1. 面试技巧   2. 将近200家企业真实面试题题   3. 老师一对一辅导,从简历到面试复盘 已解决:北京2000+人就业,西安72人就业,成都221人就业,湖南39人就业,广东1000+人就业捷径我告诉你了,别人已经找到工作了,你是否愿意在过年前找到工作?就看你了。

November 4, 2019 · 1 min · jiezi

腾讯算法面试题64匹马8个跑道选出最快的4匹最少需要几次

第一步:所有64匹,随机分8组,每组跑一遍,把每组后面4个淘汰掉。用了8次,剩余32匹 第二步:剩余的4个里面,用每组最快的那个组成一个新组,跑一遍,把后面4个所在组淘汰掉。用了1次,剩余16匹 第三步:把第二步跑第一名的单独拿出来,把第二步跑第二名的拿出来,剩余8匹,让这8匹跑一次,如果跑的最快的在两个以上的组,用第二快替换掉第三名就得到最快的4匹马。如果最快的都在第一名所在的组,进入第四步。用了1次。 第四步:用第一名所在组的后3名加第二步的第二名组成一组,把最慢的一个淘汰掉,和第二步的第一名加起来就是最终的结果,最快的4匹马。用了1次。 所以最少要10次或者11次能找出最快的4匹马。

November 4, 2019 · 1 min · jiezi

一分钟面试题令人挠头的三目运算符

面试题 提问:当 a=1,b=2 时,test1 方法的执行结果是什么?思考一分钟。 答案: 解析在使用三目运算符时,尽量保证两个返回值的类型一致,不然会触发类型转换,转换规则如下: 如果返回值 X 和返回值 Y 是同种类型,那么返回类型毫无疑问就是这种类型。如果两个返回值 X 和 Y 的类型不同,那么返回值类型为他们两最接近的父类。举例: // String 和 Boolean 都实现了 Serializable 接口Serializable serializable = a == b ? "true" : Boolean.FALSE;// 所有类都继承了 Object 类Object o = a == b ? new ArrayList<>() : new TernaryOperatorDemo();对于基本数据类型,如果其中一个返回值 X 类型为byte、short或者char,另一个返回值 Y 类型为int,那么若在编译期就能判断出 Y 的取值范围在 X 的取值范围之内,则返回类型为 X 的类型,反之则为 Y 的类型。如果返回值 X 类型不为以上几种,则会触发隐藏类型转换。当基本数据类型和对象数据类型相遇时,三目运算符默认返回结果为基本数据类型。了解以上规则之后,我们再看来一下 test1 方法。 private static void test1(int a, int b) { // 触发隐藏类型转换,int 类型 9 转为 9.0D System.out.println(a == b ? 9.9 : 9); // 编译期判断,98 在 char 之内,转为 b System.out.println(a == b ? 'a' : 98); // 编译期判断,超出char范围,统一转 int System.out.println(a == b ? 'a' : Integer.MAX_VALUE); // 编译期时无法判断 b 的取值,触发隐藏类型转换,统一转 int System.out.println(a == b ? 'a' : b); System.out.println(a != b ? 'a' : b); Map<String, Long> map = new HashMap<>(); map.put("b", 1L); // 基本数据类型和对象数据类型相遇时,默认转为基本数据类, // map.get("a") 返回 null,转为基本数据类型时,报空指针异常 System.out.println(map == null ? -1L : map.get("a"));}作业如何修改 test1 方法,使得代码运行时不抛空指针异常,请至少提供一种解决方案哦。 ...

November 4, 2019 · 1 min · jiezi

记一次大厂的面试过程

前言2019年6月中旬,实在厌倦了之前平平淡淡的工作和毫不起眼的薪资,不顾亲人的反对,毅然决然地决定只身前往沿海城市,想着找到一份更加具有挑战性的工作,来彻彻底底地重新打磨自己,同时去追求更好的薪资待遇。当然在此之前,自己每天下班后都会利用业余时间抓紧复习巩固刷题等等,大概从3月份开始的吧,持续了3个多月。而后从6月中旬面试一直到6月底,中间大概两个星期,其实我的学历和背景并不突出,但是我个人感觉可能是因为自己简历做的稍微还行(后面我可能会单独出一篇文章,来聊聊我做简历时的一点点心得),让大厂的HR能够多看几眼,中间面过的公司包括喜马拉雅、携程、哔哩哔哩、流利说、蜻蜓FM、爱回收等,陆陆续续拿到4,5个Offer吧,如今已经转正,所以在这里记录下之前的部分面试题,和大家一起分享交流。 正文1. 烈熊网络这家公司其实我也没有太了解过,是我前同事推荐的,说里面的薪资待遇不错,然后我当时也有空闲时间,所以就去试试了,虽然公司名气没有上面提到的公司大,但是他的面试题我觉得还是挺有分量的。1.1 请说出下面代码的执行顺序async function async1() { console.log(1); const result = await async2(); console.log(3);}async function async2() { console.log(2);}Promise.resolve().then(() => { console.log(4);});setTimeout(() => { console.log(5);});async1();console.log(6);我的回答是[1,2,6,4,3,5]。这道题目主要考对JS宏任务和微任务的理解程度,JS的事件循环中每个宏任务称为一个Tick(标记),在每个标记的末尾会追加一个微任务队列,一个宏任务执行完后会执行所有的微任务,直到队列清空。上题中我觉得稍微复杂点的在于async1函数,async1函数本身会返回一个Promise,同时await后面紧跟着async2函数返回的Promise,console.log(3)其实是在async2函数返回的Promise的then语句中执行的,then语句本身也会返回一个Promise然后追加到微任务队列中,所以在微任务队列中console.log(3)在console.log(4)后面,不太清楚的同学可以网上查下资料或者关注我的公众号「前端之境」,我们可以一起交流学习。 1.2 手动实现Promise,写出伪代码幸运的是在面试前刚好查阅了下这部分的资料,所以回答过程中还算得心应手,主要是需要遵循Promise/A+规范: (1) 一个promise必须具备三种状态(pending|fulfilled(resolved)|rejected),当处于pending状态时,可以转移到fulfilled(resolved)状态或rejected状态,处于fulfilled(resolved)状态或rejected状态时,状态不再可变; (2) 一个promise必须有then方法,then方法必须接受两个参数: // onFulfilled在状态由pending -> fulfilled(resolved) 时执行,参数为resolve()中传递的值// onRejected在状态由pending -> rejected 时执行,参数为reject()中传递的值promise.then(onFulfilled,onRejected)(3) then方法必须返回一个promise: promise2 = promise1.then(onFulfilled, onRejected);实现代码直接贴出来吧: 参考自:实现一个完美符合Promise/A+规范的Promisefunction myPromise(constructor){ let self=this; self.status="pending" //定义状态改变前的初始状态 self.value=undefined;//定义状态为resolved的时候的状态 self.reason=undefined;//定义状态为rejected的时候的状态 self.onFullfilledArray=[]; self.onRejectedArray=[]; function resolve(value){ if(self.status==="pending"){ self.value=value; self.status="resolved"; self.onFullfilledArray.forEach(function(f){ f(self.value); //如果状态从pending变为resolved, //那么就遍历执行里面的异步方法 }); } } function reject(reason){ if(self.status==="pending"){ self.reason=reason; self.status="rejected"; self.onRejectedArray.forEach(function(f){ f(self.reason); //如果状态从pending变为rejected, //那么就遍历执行里面的异步方法 }) } } //捕获构造异常 try{ constructor(resolve,reject); }catch(e){ reject(e); }}myPromise.prototype.then=function(onFullfilled,onRejected){ let self=this; let promise2; switch(self.status){ case "pending": promise2 = new myPromise(function(resolve,reject){ self.onFullfilledArray.push(function(){ setTimeout(function(){ try{ let temple=onFullfilled(self.value); resolvePromise(temple) }catch(e){ reject(e) //error catch } }) }); self.onRejectedArray.push(function(){ setTimeout(function(){ try{ let temple=onRejected(self.reason); resolvePromise(temple) }catch(e){ reject(e)// error catch } }) }); }) case "resolved": promise2=new myPromise(function(resolve,reject){ setTimeout(function(){ try{ let temple=onFullfilled(self.value); //将上次一then里面的方法传递进下一个Promise状态 resolvePromise(temple); }catch(e){ reject(e);//error catch } }) }) break; case "rejected": promise2=new myPromise(function(resolve,reject){ setTimeout(function(){ try{ let temple=onRejected(self.reason); //将then里面的方法传递到下一个Promise的状态里 resolvePromise(temple); }catch(e){ reject(e); } }) }) break; default: } return promise2;}function resolvePromise(promise,x,resolve,reject){ if(promise===x){ throw new TypeError("type error") } let isUsed; if(x!==null&&(typeof x==="object"||typeof x==="function")){ try{ let then=x.then; if(typeof then==="function"){ //是一个promise的情况 then.call(x,function(y){ if(isUsed)return; isUsed=true; resolvePromise(promise,y,resolve,reject); },function(e){ if(isUsed)return; isUsed=true; reject(e); }) }else{ //仅仅是一个函数或者是对象 resolve(x) } }catch(e){ if(isUsed)return; isUsed=true; reject(e); } }else{ //返回的基本类型,直接resolve resolve(x) }}1.3 请说出以下打印结果let a = {a: 10};let b = {b: 10};let obj = { a: 10};obj[b] = 20;console.log(obj[a]);我的回答是:20。这道题目主要考对JS数据类型的熟练度以及对ES6中属性名表达式的理解。在上题中obj[b] = 20的赋值操作后,obj其实已经变成了{a: 10, [object Object]: 20},这是因为如果属性名表达式是一个对象的话,那么默认情况下会自动将对象转为字符串[object Object],最后一步获取obj[a]时,a本身也是一个对象,所以会被转换为获取obj[object Object]也就是上一步赋值的20。 ...

November 3, 2019 · 6 min · jiezi

前端面试每日31周汇总20191103

《论语》,曾子曰:“吾日三省吾身”(我每天多次反省自己)。 前端面试每日3+1题,以面试题来驱动学习,每天进步一点! 让努力成为一种习惯,让奋斗成为一种享受!相信 坚持 的力量!!!学习不打烊,充电加油只为遇到更好的自己,365天无节假日,每天早上5点纯手工发布面试题(死磕自己,愉悦大家)。希望大家在这浮夸的前端圈里,保持冷静,坚持每天花20分钟来学习与思考。在这千变万化,类库层出不穷的前端,建议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢迎大家到Issues交流,鼓励PR,感谢Star,大家有啥好的建议可以加我微信一起交流讨论!希望大家每日去学习与思考,这才达到来这里的目的!!!(不要为了谁而来,要为自己而来!)毕竟一个人的能力有限,集体的力量才是无限的!欢迎大家一起来贡献题目,为前端面试每日3+1开源社区贡献力量!点击 我也要出题 贡献你的题目吧,让大家一起来挑战你的题目! 【推荐】欢迎跟 jsliang 一起折腾前端,系统整理前端知识,目前正在折腾 LeetCode,打算打通算法与数据结构的任督二脉。GitHub 地址 html解释下为什么<p> </p>会换两行?你知道p标签和br标签两者的区别是什么吗?如何在页面中插入TAB符号(制表符)说下cookie都有哪些缺点?举例说明a标签的作用都有哪些?请举例说明关于html的引用标签有哪些?请举例说明html支持的数学符号有哪些?css举例说明伪类:focus-within的用法如何用css自定义滚动条?能做到所有浏览器兼容吗?想要做兼容怎么办呢?border-radius:50%和border-radius:100%有什么区别?如何使用CSS实现段落首字母或首字放大效果?如何给段落的首行缩进?你有去看过或者了解过css的标准文档吗?你知道CSS的标准发布流程吗?js你有用过哪些3D渲染的库?页面的编码和被请求的资源编码不一致时如何处理?ajax的请求状态有哪几种?请介绍下js的数据类型写一个方法找出一段话里面出现频率最多的词请使用js实现一个省市县级联的效果用js实现一个轮播图,并简述有哪些实现的方法软技能你知道什么是内网穿透吗?有没有玩过?你要是在家时,公司网站出问题了你是怎么解决的?假设有一个场景,需要前端自己计算十万级别或更多的数据,你有解决什么方案呢?你有做过H5的游戏开发吗?说说它的开发步骤你有做过Hybrid APP开发吗?说说你的经验你是计算机专业的吗?你们上学都学了哪些内容?你知道开发好的功能要自测吗?你一般是怎么自测的呢?全部所有 交流讨论欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个Star, 同时欢迎加入 “前端面试每日3+1” 微信群(扫个人微信号邀请入群)相互交流。

November 3, 2019 · 1 min · jiezi

web前端面试题HTML篇持续更新

1,Doctype作用?标准模式与兼容模式各有什么区别? (1)、<!DOCTYPE>声明位于位于HTML文档中的第一行,处于 <html> 标签之前。告知浏览器的解析器 用什么文档标准解析这个文档。DOCTYPE不存在或格式不正确会导致文档以兼容模式呈现。 (2)、标准模式的排版 和JS运作模式都是以该浏览器支持的最高标准运行。在兼容模式中,页面以宽松的向后兼容的方式显示,模拟老式浏览器的行为以防止站点无法工作。2,HTML5 为什么只需要写 <!DOCTYPE HTML>? HTML5 不基于 SGML,因此不需要对DTD进行引用,但是需要doctype来规范浏览器的行为(让浏览器按照它们应该的方式来运行); 而HTML4.01基于SGML,所以需要对DTD进行引用,才能告知浏览器文档所使用的文档类型。3,行内元素有哪些?块级元素有哪些? 空(void)元素有那些? 首先:CSS规范规定,每个元素都有display属性,确定该元素的类型,每个元素都有默认的display值,如div的display默认值为“block”,则为“块级”元素;span默认display属性值为“inline”,是“行内”元素。 (1)行内元素有:a b span img input select strong(强调的语气) (2)块级元素有:div ul ol li dl dt dd h1 h2 h3 h4…p (3)常见的空元素: <img> <input> <link> <meta> 鲜为人知的是: <area> <base> <col> <command> <embed> <keygen> <param> <source> <track> <wbr>4,页面导入样式时,使用link和@import有什么区别? (1)link属于XHTML标签,除了加载CSS外,还能用于定义RSS, 定义rel连接属性等作用;而@import是CSS提供的,只能用于加载CSS; (2)页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载; (3)import是CSS2.1 提出的,只在IE5以上才能被识别,而link是XHTML标签,无兼容问题;5,介绍一下你对浏览器内核的理解? 主要分成两部分:渲染引擎(layout engineer或Rendering Engine)和JS引擎。 (1)渲染引擎:负责取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入CSS等),以及计算网页的显示方式,然后会输出至显示器或打印机。浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不相同。所有网页浏览器、电子邮件客户端以及其它需要编辑、显示网络内容的应用程序都需要内核。 (2)JS引擎则:解析和执行javascript来实现网页的动态效果。 最开始渲染引擎和JS引擎并没有区分的很明确,后来JS引擎越来越独立,内核就倾向于只指渲染引擎。6,常见的浏览器内核有哪些? Trident内核:IE,MaxThon,TT,The World,360,搜狗浏览器等。[又称MSHTML] Gecko内核:Netscape6及以上版本,FF,MozillaSuite/SeaMonkey等 Presto内核:Opera7及以上。 [Opera内核原为:Presto,现为:Blink;] Webkit内核:Safari,Chrome等。 [ Chrome的:Blink(WebKit的分支)]7,html5有哪些新特性、移除了那些元素?如何处理HTML5新标签的浏览器兼容问题?如何区分 HTML 和 HTML5? ...

November 2, 2019 · 1 min · jiezi

面试-必须要会的50个React面试题

前言如果你是一位有抱负的前端程序员并准备面试,那么这篇文章很适合你。本文是你学习和面试 React 所需知识的***指南。 JavaScript 工具缓慢而稳定地在市场中扎根,对 React 的需求呈指数级增长。选择合适的技术来开发应用或网站变得越来越有挑战性。其中 React 被认为是增长最快的 Javascript 框架。 截至今天,Github 上约有1,000名贡献者。 Virtual DOM 和可重用组件等独特功能吸引了前端开发人员的注意力。尽管它只是 MVC(模型 - 视图 - 控制器)中“视图”的库,但它对 Angular,Meteor,Vue 等全面的框架也构成了强力的挑战。下图为流行的 JS 框架的趋势: JS 框架的趋势 React 面试题以下是面试官最有可能问到的50 个 React 面试题和答案。为方便你学习,我对它们进行了分类: · 基本知识 · React 组件 · React Redux · React 路由 基本知识1、区分Real DOM和Virtual DOM 2、什么是React?· React 是 Facebook 在 2011 年开发的前端 JavaScript 库。 · 它遵循基于组件的方法,有助于构建可重用的UI组件。 · 它用于开发复杂和交互式的 Web 和移动 UI。 · 尽管它仅在 2015 年开源,但有一个很大的支持社区。 ...

October 22, 2019 · 2 min · jiezi

HR视角面了十几个Android开发候选人的一些总结及建议

背景公司前段时间冲上了App Store的第一,为了满足产品的各种需求,公司技术团队扩招,基于这种情况下,前段时间基本上都在面试,上上下下也面了十几个人。趁今天在家休息,就有了写这篇文章的打算。 因为公司都是和猎头公司合作,所以候选人背景基本上都是3年以上开发者。 面试总结 因为项目要快速开发,所以我问的他自己常见的一些第三方框架,数据库用SQLite,开发过程中自己写SQLite语句。我让他写一条学生按成绩排序的SQL语句都出问题。这个就直接pass了。 候选人是做内置应用的,但是对于优化这一块不是很熟悉,直接pass了。 这个是另外一个同事面的结论,pass!pass!pass!要招的就是快速开发,UI只掌握理论,开源框架都没使用过,这还怎么过? 前面感觉还不错,但是到后面事件分发不熟悉,那还怎么搞?pass 这个候选人感觉还是回答比较诚实的,懂就是懂,不懂就是不懂,好感还是有的,但是准备还是不够充分,很多基础的点没回答上。 这个没什么好说的,事件分发过不了直接pass。 技术一般,但简历过于优化。pass! 自定义View的流程都不清楚,基础不牢固,sorry。 事件分发过不了,这一点直接pass。 因为Hierachy那段时间自己也刚好在使用,所以候选人在使用AS 3.2.0的时候能直接通过AS打开确实不应该。 事件分发不熟悉,pass。 这个是面试过程的唯一一个女生,国内一个直播平台背景。前面印象挺不错的(毕竟是妹子,天生的优势),问大的点貌似都懂一点,但是问一些基础的知识点问题就比较大,问事件分发viewGroup的dispatchTouchEvent若返回false,此时事件分发顺序是怎样的?答会回调ViewGroup的onTouchEvent事件。因为是妹子,我告诉她回答有点问题,最终还是陪她看了一遍dispatchTouchEvent的源码,简单分析了一波。哎,最后她自己感觉她自己挂了,ok,pass。一些自己的看法 很多人都说今年是互联网寒冬,找工作不好找,其实不然,只要你自己技术到位,基本上都是各大公司的抢手人才。 再说说面试过程中我常问的一些问题: 1.自定义View相关问题;2.如何让点击事件和常按事件同时响应?3.viewGroup的dispatchTouchEvent若返回false,此时事件分发顺序是怎样的?4.如何处理ViewPager 和RecyclerView的滑动冲突?5.RecyclerView如何一次滑动一个?6.Hanlder的原理及looper的作用?7.开发过程中常用的第三方库有哪些?看过哪些的源码?8.性能检测及使用的工具?上面是我常问的一些问题,而这些恰恰都是基本的问题,然而大部分候选人都不能回答的很好!而我感觉这恰恰反应了行业的现状,很多人,只copy代码,实现就ok了,很少看其中的原理,下次继续copy,但是一到面试跳槽,也不复习,一问三不知。浪费彼此时间。你说你开发多年,没有github,没有博客,然后问你个几个原理还不知道,这谁顶得住? 最后,还是希望写点建议,至于有没有用,自行参考定夺,喷子太多,害怕ing……。 别老问寒冬不寒冬?你先问自己技术到位不到位?面试一家公司之前,尽可能的准备充分,上面所有的这些总结都会反馈给猎头,而恰恰同一个猎头推荐的候选人会在同一个问题上翻车!所以,如果是猎头推荐,多问下其他面试者的反馈,相信猎头们不会吝啬的。简历上的除非真精通,不然不要写精通,你写个了解熟悉,然后深入谈下去发现你好像特别熟悉,好感度会提高很多。简历上不会的千万不要写,除非你觉得你今天人品爆表,面试官这个一定不会问!简历上越熟悉越擅长的写在越前面。ok,面试官一般会从一个问题入手,衍生其他问题,越前面越有机会进入你自己熟悉的话题。(至少我是这样)!带上自己得意的作品!带上自己吃饭的家伙,自己项目的代码,你已经赢了一半了。(至少我之前面试就这么干,你要看什么功能?你要实现什么?有什么问题?我当你面解决这个问题。什么?你觉得我说得不对?来来来,咱们直接看源码,主动权在自己手里!)该有的礼貌要有,该低调还是要低调。这个是对极少数人的建议,你技术再好,一副老子天下第一的样子,那不好意思,请另谋高就。做好有自己的积累,github,博客文章,不仅仅能提升自己的写作能力,积累经验,也是面试过程中别人了解你的绝佳途径。限时分享Android学习PDF+架构视频+面试文档+源码笔记 在这里分享一份我自己收录整理的Android学习PDF+架构视频+面试文档+源码笔记,还有高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习 如果你有需要的话,可以点赞+转发,关注我,然后加入Android开发交流群(820198451)免费领取

October 17, 2019 · 1 min · jiezi

寒冬三年经验前端面试总结含头条百度饿了么滴滴等之手写题一

前言不论是寒冬还是暖冬,找工作之前都需要做好充足的准备,面试的时候才能做到游刃有余。此文是把我最近找工作准备的以及笔试面试中涉及到的手写题做一个总结。给自己,也给需要的同学。手写题是比较好准备的一个环节,大部分公司考察的题也就那么多,大都不会超出范围。 往期"寒冬"三年经验前端面试总结(含头条、百度、饿了么、滴滴等)防抖 & 节流原理都是利用闭包保存变量。防抖是任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行,一般用于输入框实时搜索;节流是规定函数在指定的时间间隔内只执行一次,一般用于scroll事件。 // 防抖function debounce(fn,time){ let timer = null; return function(){ if(timer){ clearTimeout(timer) } timer = setTimeout(()=>{ fn.apply(this,arguments) },time) }}// 节流function throttle(fn,time){ let canRun = true; return function(){ if(!canRun){ return } canRun = false; setTimeout(() => { fn.apply(this,arguments); canRun = true; },time) }}深拷贝深拷贝是一个老生常谈的问题。几年前面试就考,现在面试仍然会考。主要考察的是递归、数组和对象的存储。 function deepClone(obj) { var result = Array.isArray(obj) ? [] : {}; for (var key in obj) { if (obj.hasOwnProperty(key)) { if (typeof obj[key] === 'object' && obj[key]!==null) { result[key] = deepCopy(obj[key]); } else { result[key] = obj[key]; } } } return result; }function deepClone(arr){ return JSON.parse(JSON.stringify(arr))}数组乱序乱序也是常考的一道题。 ...

October 16, 2019 · 2 min · jiezi

Java程序员面试跳槽涨薪必备多线程和并发面个阿里P6轻轻松

一. ThreadLocal 的原理ThreadLocal 相当于一个容器, 用于存放每个线程的局部变量。 ThreadLocal 实例通常来说都是 private static 类型的。 ThreadLocal 可以 给一个初始值,而每个线程都会获得这个初始化值的一个副本,这样才能保证 不同的线程都有一份拷贝。 一般情况下,通过 ThreadLocal.set() 到线程中的对象是该线程自己使用 的对象,其他线程是访问不到的,各个线程中访问的是不同的对象。如果 ThreadLocal.set()进去的东西本来就是多个线程共享的同一个对象,那么多个 线程的 ThreadLocal.get()取得的还是这个共享对象本身,还是有并发访问问 题。 向 ThreadLocal 中 set 的变量是由 Thread 线程对象自身保存的,当用户 调 用 ThreadLocal 对象的 set(Object o) 时 , 该方法则通过 Thread.currentThread() 获取当前线程, 将变量存入线程中的 ThreadLocalMap 类的对象内,Map 中元素的键为当前的 threadlocal 对象, 而值对应线程的变量副本。 public T get() { Thread t = Thread.currentThread(); //每个 Thread 对象内都保存一个 ThreadLocalMap 对象。 ThreadLocalMap map = getMap(t); //map 中 元 素 的 键 为 共 用 的 threadlocal 对象,而值为对应线程的变量副本。 if (map != null) return (T)map.get(this); } T value = initialValue(); createMap(t, value); return value;}public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value);}ThreadLocalMap getMap(Thread t) { return t.threadLocals;}void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue);}二. Collections.synchronizedXX 方法的原理。public E get(int index) { synchronized (mutex) { return list.get(index); }}public E set(int index, E element) { synchronized (mutex) { return list.set(index,element); }}public void add(int index, E element) { synchronized (mutex) { list.add(index, element); }}public E remove(int index) { synchronized (mutex) { return list.remove(index); }}在返回的列表上进行迭代时,用户必须手工在返回的列表上进行同步: ...

October 15, 2019 · 3 min · jiezi

Java程序员必备Linux的面试常见问题及面试题你知道多少

一. 常用命令1. 编辑相关①. awk NF:字段总数NR:第几行数据FS:分隔字符②. sed -n-i 直接修改4a:在第四行后添加4i:在第四行前插入1,5c sting:用sting替换1到5行的内容s/要被替换的字符串/新的字符串/g③. sort -t-nr sort |uniq -c |sort -nr④. tr -d:删除[a-z] [A Z]:替换2. 查看负载相关①. top load average cpu 里面的几个数字代表什么意思,怎么衡量,为什么 load average 50 算高还是低?怎么计算的?系统在1,5,15分钟的平均工作负载,进程队列中的平均进程数量。一般不能大于系统逻辑CPU的个数/proc/loadavg关键参数Task:僵尸进程的数量CPU:%wa IOwaitMem:Swap:要尽可能的少用②. uptime ③. free:读取自文件:/proc/meminfo buffer存放要写回到磁盘的数据cache存放从磁盘上读出的数据-buffers/cache,表示一个应用程序认为系统被用掉多少内存;被程序实实在在占用的内存+buffers/cache,表示一个应用程序认为系统还有多少内存;可用的内存数。④. vmstat:动态的了解系统资源运行 -d:磁盘r:等待运行的进程数,r<5表示状态好b:处于非中断睡眠状态的进程数,b≈0表示状态好id:CPU闲置时间如果r经常大于3或4,且id经常小于50,表示CPU负荷很重⑤. ps aux-l⑥. lsof:列出被进程所打开的文件名 ⑦. pwd首先获取当前目录的i节点编号,但是并不能知道当前目录的名称,我们切换到其的父目录,在里面寻找当前i节点编号对应的文件名即可。终止条件是"."和".."指向同一个i节点,我们可以以此判断是否发到达了根目录 ⑧. pgrep 3. 查找①. grep -n-v-A-B②. find 时间: 4:4天前的那一天+4:大于等于5天之前-4:小于等于4天之内-exec 命令 { } ;4. 磁盘①. du -sh /du -cks * | sort -rn | head -n 10评估目录所占容量,通过将指定文件系统中所有的目录、符号链接和文件使用的块数累加得到该文件系统使用的总块数du命令是用户级的程序,它不考虑Meta Data,而df命令则查看文件系统的磁盘分配图并考虑Meta Data。du以文件名、目录名为依据计算空间使用的,而df是以硬盘块使用情况来计算空间使用的。-sm 以M为单位列出文件容量②. df ...

October 14, 2019 · 2 min · jiezi

Spring-Boot-必问面试题精选

1.简介自Spring Boot诞生以来,就引起了业界轰动,目前越来越多的公司技术选型选择拥抱Spring Boot。所以Spring Boot也成为面试必问的问题之一。接下来小胖哥总结了一些来开阔你的思路。 2.问题好了接下来直奔主题说说经常在面试中问到的 Spring Boot 面试题 Q1。Spring和Spring Boot有什么区别?Spring Framework提供了多种功能,使Web应用程序的开发更加容易。这些功能包括依赖注入,数据绑定,面向方面的编程,数据访问等等。随着Spring社区的壮大,Spring慢慢变得越来越复杂,不再像开始宣称的那么轻量级。 开发应用程序的配置量越来越大令开发者头疼。这时Spring Boot就派上用场了 - 它采用“约定大于配置”的思想简化了配置,对Spring提供的功能和配置而且将一些功能抽象成为“Starter”开箱即用、按需引用。极大地简化了开发。 Q2。我们如何使用Maven设置Spring Boot应用程序?我们可以像在任何其他库中一样在Maven项目中包含Spring Boot。但是,最好的方法是从spring-boot-starter-parent项目继承并声明依赖于Spring Boot启动器。这样做可以让我们的项目重用Spring Boot的默认设置。继承spring-boot-starter-parent项目非常简单 - 我们只需要在 pom.xml 中指定一个 parent 元素: 我们可以在Maven 中央仓库找到最新版本的 spring-boot-starter-parent。上面的方式很方便但是并不一定符合实际需要。例如公司要求所有项目依赖构建从一个标准BOM开始,我们就不能按上面的方式进行。在这种情况下,我们可以进行如下引用: 然后在 dependencies 标签下引用Spring Boot 的starters 就行了。 Q3。Spring boot 中的starter是什么?依赖管理对于项目至关重要。当项目足够复杂时,管理依赖项可能会变成一场噩梦,因为涉及的组件太多了。这就是Spring Boot 的 starter 就派上用场了。每个starter都可以为我们提供所需要的Spring技术的一站式服务。并且以一致的方式传递和管理其他所需的依赖关系。所有官方starter都在 org.springframework.boot 组下,其名称以 spring-boot-starter- 开头 。非官方的starter的名称在前,如 mybatis-spring-boot-starter。这种命名模式使得查找启动器变得很容易,尤其是在使用支持按名称搜索依赖关系的IDE时。但是这个不是绝对的,有些开发者可能不遵从这种契约。目前大概有超过50种官方starter。最常用的是: spring-boot-starter: 核心启动器,包括自动配置支持,日志记录和YAMLspring-boot-starter-aop: 使用Spring AOP和AspectJ进行面向方面编程的初学者spring-boot-starter-data-jpa: 使用Spring Data JPA和Hibernate的启动器spring-boot-starter-jdbc: 用于将JDBC与HikariCP连接池一起使用的启动器spring-boot-starter-security: 使用Spring Security的启动器spring-boot-starter-test: 用于测试Spring Boot应用程序的启动器spring-boot-starter-web: 使用Spring MVC构建Web的启动器,包括RESTful应用程序其他starter 可去spring.io查询 Q4。如何禁用特定的自动配置?如果我们要禁用特定的自动配置,我们可以使用@EnableAutoConfiguration注解的exclude属性来指示它。如下禁用了数据源自动配置DataSourceAutoConfiguration: ...

October 14, 2019 · 1 min · jiezi

寒冬三年经验前端面试总结

前言跳槽是每个人的职业生涯中都要经历的过程,不论你是搜索到的这篇文章还是无意中浏览到的这篇文章,希望你没有白白浪费停留在这里的时间,能给你接下来或者以后的笔试面试带来一些帮助。 2019也许是互联网未来10年中最好的一年。WINTER IS COMING。但是如果你不真正的自己去尝试尝试,你永远不知道市面上的行情如何。这次找工作下来,我自身感觉市场并没有那么可怕,也拿到了几个大厂的offer。在此进行一个总结,给自己,也希望能帮助到需要的同学。 面试准备面试准备根据每个人掌握的知识不同,准备的时间也不一样。现在对于前端岗位,以前也许不是很重视算法这块,但是现在很多公司也都会考。建议大家平时有空的时候多刷刷leetcode。算法的准备时间比较长,是一个长期的过程。需要在掌握了大部分前端基础知识的情况下,再有针对性的去复习算法。面试的时候算法能做出来肯定加分,但做不出来也不会一票否决,面试官也会给你提供一些思路。 笔试题笔试题一般考的都是基础知识,复习基础知识建议看书,高程和你不知道的JS都行,会讲的比较细。 CSScss基本上每个公司也都会问,但是问的不会很深,都是一些常见的问题。 盒模型垂直居中方法三栏布局选择器权重计算方式清除浮动的方法flex什么是BFC、可以解决哪些问题position属性如何实现一个自适应的正方形如何用css实现一个三角形手写题手写题每个公司都会有,范围也比较固定,如果之前好好准备的话,应该没什么问题。 防抖和节流深拷贝数组去重、数组乱序手写call、apply、bind继承(ES5/ES6)sleep函数实现promise实现promise.all实现promise.retry将一个同步callback包装成promise形式写一个函数,可以控制最大并发数jsonp的实现eventEmitter(emit,on,off,once)实现instanceof实现new实现数组flat、filter等方法lazyManES6现在基本上都会使用ES6开发。ES6也成为了一个面试必考点。一般面试官都会问用过ES6的哪些新特性,再针对你所回答的进行深入的提问。 let、const、var区别箭头函数与普通函数的区别变量的结构赋值promise、async await、Generator的区别ES6的继承与ES5相比有什么不同js模块化(commonjs/AMD/CMD/ES6)浏览器相关知识浏览器相关知识几乎是每个公司都会问到的考点,里面涉及的东西也比较多。其中缓存、http2、跨域必问。 从输入URL到呈现页面过程强缓存、协商缓存、CDN缓存HTTP2HTTP状态码三次握手与四次挥手跨域(JSONP/CORS)跨域时如何处理cookie垃圾回收机制web安全一般我都会从xss和csrf说起。 https什么是xss,如何预防什么是csrf,如何预防为什么会造成csrf攻击事件循环事件循环绝对是一个必考题。其中涉及到宏任务、微任务、UI渲染等的执行顺序,浏览器端的必须要掌握,node端的有精力的最好也能掌握。 框架(vue)因为我一直用的都是vue框架,所以问的也都是跟vue相关的。vue中的高频题也不外乎双向绑定、虚拟dom、diff算法这些。 watch与computed的区别vue生命周期及对应的行为vue父子组件生命周期执行顺序组件间通讯方法如何实现一个指令vue.nextTick实现原理diff算法如何做到的双向绑定虚拟dom为什么快如何设计一个组件webpackwebpack也基本上成了必考的内容,一般会问是否配置过webpack、做过哪些优化之类的。 用过哪些loader和pluginloader的执行顺序为什么是后写的先执行webpack配置优化webpack打包优化(happypack、dll)plugin与loader的区别webpack执行的过程如何编写一个loader、plugintree-shaking作用,如何才能生效性能优化首屏加载如何优化一个网页从请求到呈现花了很长时间,如何排查因为之前的经历大部分都集中在PC端,所以移动端的经验比较少。面试官也不会一直问你移动端的东西,问也就问一些常见的问题,比如1px问题、如何适配等。react用的也不多,问的也不多,也就会问问react与vue的对比之类的问题。 基本的问题过了之后,有的面试官还喜欢问一些开放性的问题。比如平时都是如何学习的、最近了解了什么新技术、未来的职业规划、为了达到这个目标目前做了什么努力等等。 总结的基本上就是这么多了,上面问题的答案我也会陆续给出,给大家一个参考。喜欢的可以点个收藏哈~最后预祝看了此篇文章的小伙伴们都能收获多多的offer,找到自己满意的工作~

October 7, 2019 · 1 min · jiezi

推荐收藏系列一文理解JVM虚拟机内存垃圾回收性能优化解决面试中遇到问题

一. JVM内存区域的划分1.1 java虚拟机运行时数据区java虚拟机运行时数据区分布图: JVM栈(Java Virtual Machine Stacks): Java中一个线程就会相应有一个线程栈与之对应,因为不同的线程执行逻辑有所不同,因此需要一个独立的线程栈,因此栈存储的信息都是跟当前线程(或程序)相关信息的,包括局部变量、程序运行状态、方法返回值、方法出口等等。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。堆(Heap): 堆是所有线程共享的,主要是存放对象实例和数组。处于物理上不连续的内存空间,只要逻辑连续即可方法区(Method Area): 属于共享内存区域,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据常量池(Runtime Constant Pool): 它是方法区的一部分,用于存放编译期生成的各种字面量和符号引用。本地方法栈(Native Method Stacks):其中,堆(Heap)和JVM栈是程序运行的关键,因为: 栈是运行时的单位(解决程序的运行问题,即程序如何执行,或者说如何处理数据),而堆是存储的单位(解决的是数据存储的问题,即数据怎么放、放在哪儿)。堆存储的是对象。栈存储的是基本数据类型和堆中对象的引用;(参数传递的值传递和引用传递)那为什么要把堆和栈区分出来呢?栈中不是也可以存储数据吗? 从软件设计的角度看,栈代表了处理逻辑,而堆代表了数据,分工明确,处理逻辑更为清晰体现了“分而治之”以及“隔离”的思想。堆与栈的分离,使得堆中的内容可以被多个栈共享(也可以理解为多个线程访问同一个对象)。这样共享的方式有很多收益:提供了一种有效的数据交互方式(如:共享内存);堆中的共享常量和缓存可以被所有栈访问,节省了空间。栈因为运行时的需要,比如保存系统运行的上下文,需要进行地址段的划分。由于栈只能向上增长,因此就会限制住栈存储内容的能力。而堆不同,堆中的对象是可以根据需要动态增长的,因此栈和堆的拆分,使得动态增长成为可能,相应栈中只需记录堆中的一个地址即可。堆和栈的结合完美体现了面向对象的设计。当我们将对象拆开,你会发现,对象的属性即是数据,存放在堆中;而对象的行为(方法)即是运行逻辑,放在栈中。因此编写对象的时候,其实即编写了数据结构,也编写的处理数据的逻辑。1.2 堆(Heap)和JVM栈:1.2.1 堆(Heap) Java堆是java虚拟机所管理内存中最大的一块内存空间,处于物理上不连续的内存空间,只要逻辑连续即可,主要用于存放各种类的实例对象。该区域被所有线程共享,在虚拟机启动时创建,用来存放对象的实例,几乎所有的对象以及数组都在这里分配内存(栈上分配、标量替换优化技术的例外)。 在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor(S0)、To Survivor(S1)。如图所示: 堆的内存布局: 这样划分的目的是为了使jvm能够更好的管理内存中的对象,包括内存的分配以及回收。 而新生代按eden和两个survivor的分法,是为了 有效空间增大,eden+1个survivor;有利于对象代的计算,当一个对象在S0/S1中达到设置的XX:MaxTenuringThreshold值后,会将其挪到老年代中,即只需扫描其中一个survivor。如果没有S0/S1,直接分成两个区,该如何计算对象经过了多少次GC还没被释放。两个Survivor区可解决内存碎片化1.2.2 堆栈相关的参数参数描述-Xms堆内存初始大小,单位m、g-Xmx堆内存最大允许大小,一般不要大于物理内存的80%-Xmn年轻代内存初始大小-Xss每个线程的堆栈大小,即JVM栈的大小-XX:NewRatio年轻代(包括Eden和两个Survivor区)与年老代的比值-XX:NewSzie(-Xns)年轻代内存初始大小,可以缩写-Xns-XX:MaxNewSize(-Xmx)年轻代内存最大允许大小,可以缩写-Xmx-XX:SurvivorRatio年轻代中Eden区与Survivor区的容量比例值,默认为8,即8:1-XX:MinHeapFreeRatioGC后,如果发现空闲堆内存占到整个预估堆内存的40%,则放大堆内存的预估最大值,但不超过固定最大值。-XX:MaxHeapFreeRatio预估堆内存是堆大小动态调控的重要选项之一。堆内存预估最大值一定小于或等于固定最大值(-Xmx指定的数值)。前者会根据使用情况动态调大或缩小,以提高GC回收的效率,默认70%-XX:MaxTenuringThreshold垃圾最大年龄,设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率.如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活 时间,增加在年轻代即被回收的概率-XX:InitialTenuringThreshold可以设定老年代阀值的初始值-XX:+PrintTenuringDistribution查看每次minor GC后新的存活周期的阈值Note: 每次GC 后会调整堆的大小,为了防止动态调整带来的性能损耗,一般设置-Xms、-Xmx 相等。 &emsp;&emsp;&emsp;&emsp;新生代的三个设置参数:-Xmn,-XX:NewSize,-XX:NewRatio的优先级: (1).最高优先级: -XX:NewSize=1024m和-XX:MaxNewSize=1024m (2).次高优先级: -Xmn1024m (默认等效效果是:-XX:NewSize==-XX:MaxNewSize==1024m) (3).最低优先级:-XX:NewRatio=2 推荐使用的是-Xmn参数,原因是这个参数很简洁,相当于一次性设定NewSize和MaxNewSIze,而且两者相等。 1.3 jvm对象1.3.1 创建对象的方式各个方式的实质操作如下: 方式实质使用new关键调用无参或有参构造器函数创建使用Class的newInstance方法调用无参或有参构造器函数创建,且需要是publi的构造函数使用Constructor类的newInstance方法调用有参和私有private构造器函数创建,实用性更广使用Clone方法不调用任何参构造器函数,且对象需要实现Cloneable接口并实现其定义的clone方法,且默认为浅复制第三方库Objenesis利用了asm字节码技术,动态生成Constructor对象1.3.2 jvm对象分配在虚拟机层面上创建对象的步骤: ...

October 5, 2019 · 2 min · jiezi

前端知识整理2

1.ES6 语法1.ES6 模块化如何使用,开发环境如何打包?语法: import export (注意有无 default 的区别)环境: babel 编译 ES6 语法,模块化可用 webpack 和 rollup扩展: 说一下自己对模块化标准统一的期待rollup 功能单一(只做模块化的打包编译),webpack 功能强大 2.Class 和普通构造函数有何区别?(1)Class 在语法上更加贴合面向对象的写法(2)Class 实现继承更加易读、易理解(3)更易于写 Java 等后端语言的使用(4)本质还是语法糖,使用 prototype class MathHandle { constructor(x, y) { this.x = x; this.y = y; } add() { return this.x + this.y; }}const m = new MathHandle(1, 2);console.log(m.add()); // 3console.log(typeof MathHandle); // 'function'console.log(MathHandle.prototype.constructor === MathHandle); // trueconsole.log(m.__proto__ === MathHandle.prototype); // true2.原型的实际应用、原型扩展1.说一个原型的实际应用?(1)描述一下 jquery 如何使用原型(2)描述一下 zepto 如何使用原型(3)再结合自己的项目经验,说一个自己开发的例子 ...

October 5, 2019 · 8 min · jiezi

简明易理解的SpringBootApplication注解源码分析

springApplication一、@SpringBootApplication 的作用是什么? Q:springboot项目的启动类上,都会有个注解@SpringBootApplication,这个注解起到了什么作用? @SpringBootApplicationpublic class MicroServiceApplication { public static void main(String[] args) { SpringApplication.run(MicroServiceApplication.class, args); }} 我们进入@SpringBootApplication注解,发现它等价于三个注解:@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan @SpringBootConfiguration@EnableAutoConfiguration@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })public @interface SpringBootApplication { ...}1) @SpringBootConfiguration 就相当于 @Configuration @Configurationpublic @interface SpringBootConfiguration {}2) @EnabelAutoConfiguration 相当于将这两个类的实例加入到容器中AutoConfigurationImportSelector.class AutoConfigurationPackages.Registrar.class @AutoConfigurationPackage@Import(AutoConfigurationImportSelector.class)public @interface EnableAutoConfiguration { ...}@Import(AutoConfigurationPackages.Registrar.class)public @interface AutoConfigurationPackage {}AutoConfigurationImportSelector.class的作用是,注入spring.factories文件中EnableAutoConfiguration对应的类的实例,当然要经过spring.factories文件中AutoConfigurationImportFilter对应的过滤器(OnBeanCondition、OnClassCondition、OnWebApplicationCondition等等)的过滤。还要排除掉@EnableAutoConfiguration中的exclude和excludeName 具体见ConfigurationClassParser的getImports方法,其中调用了AutoConfigurationImportSelector的process方法和selectImports方法。 public Iterable<Group.Entry> getImports() { for (DeferredImportSelectorHolder deferredImport : this.deferredImports) { this.group.process(deferredImport.getConfigurationClass().getMetadata(), deferredImport.getImportSelector()); } return this.group.selectImports(); }AutoConfigurationImportSelector实现了DeferredImportSelector,所以它是解析@Configuration的最后一步。DeferredImportSelector可以和@Order搭配使用。AutoConfigurationImportSelector的意义在于引入其他包时,可以直接注入其他包的@Configuration,当然需要在其他包的resources文件夹下,新建META-INF目录,在META-INF目录下新建spring.factories文件,加入org.springframework.boot.autoconfigure.EnableAutoConfiguration = @Configuration标注的类的路径 ...

October 2, 2019 · 3 min · jiezi

SpringBoot自定义Spring-boot-Starter原理demo代码实现以及解决面试问题

github:https://github.com/Ccww-lx/Sp... 模块:spring-boot-starter-base-service SpringBoot的方便快捷主要体现之一starter pom,Spring Boot为我们提供了简化企业级开发绝大多数场景的starter pom, 只要使用了应用场景所需要的starter pom,只需要引入对应的starter即可,即可以得到Spring Boot为我们提供的自动配置的Bean。 然而,可能在很多情况下,我们需要自定义stater,这样可以方便公司内部系统调用共同的配置模块的时候可以自动进行装载配置。比如,很多公司将生产数据库的密码托管在公司的另外一个专门管理生产密码的系统上,公司每个系统需要使用的时候都需要调用其方法进行使用,现在可以通过starter自动配置的形式进行配置。 1. SpringBoot Starter源码分析 Q:@SpringBootApplication 注解中核心注解@EnableAutoConfiguration注解在starter起什么作用呢? @EnableAutoConfiguration源码分析: @Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@AutoConfigurationPackage@Import(AutoConfigurationImportSelector.class)public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {}; String[] excludeName() default {};} 可以从源码看出关键功能是@import注解导入自动配置功能类AutoConfigurationImportSelector类,主要方法getCandidateConfigurations()使用了SpringFactoriesLoader.loadFactoryNames()方法加载META-INF/spring.factories的文件(spring.factories声明具体自动配置)。 protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames( getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you " + "are using a custom packaging, make sure that file is correct."); return configurations;} ...

October 2, 2019 · 2 min · jiezi

随机洗牌算法

今天偶然看到群里的朋友说道,面试被问如何将扑克牌随机洗牌输出。笔者觉得这道题挺有意思而且挺开放性,有多种不同的实现方式。然后我就随手写了一个算法,仔细一想这个算法的优化空间挺大,于是又写出三种算法。 第一种我们通过JDK的随机算法获取一个随机下标,再通过Set集合来判断牌是否有被抽到过,如果抽到过的话,继续进行循环,直到抽到原牌数量为止。 public class ShuffleCard1 { public static int[] getShuffleCards(int[] cards) { // 获取随机数种子 Random rand = new Random(System.currentTimeMillis()); // 用Set集合存储已抽过的牌 Set<Integer> isExisted = new HashSet(); // 声明洗牌后数组 int[] shuffleCards = new int[cards.length]; // 已抽到的牌数量 int drawCount = 0; // 当抽到的牌数量没达到原牌数组的大小时循环 while (drawCount < cards.length) { // 获取一个随机下标 int index = rand.nextInt(cards.length); // 判断该下标对应的牌是否已被抽过,没有的话,抽出 if (!isExisted.contains(cards[index])) { shuffleCards[drawCount++] = cards[index]; isExisted.add(cards[index]); } } return shuffleCards; }}第二种我们分析一下,判断牌是否被抽到的方法可以进一步优化,我们可以使用位数组来进行判断效率更高,于是我们将Set改为byte数组判断牌是否抽到。 ...

September 20, 2019 · 2 min · jiezi

36-个JS-面试题为你助力金九银十面试必读

来源:javapoint译者:前端小智为了保证的可读性,本文采用意译而非直译。 想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你! 为了回馈读者,《大迁世界》不定期举行(每个月一到三次),现金抽奖活动,保底200,外加用户赞赏,希望你能成为大迁世界的小锦鲤,快来试试吧1.JS中let和const有什么用?在现代js中,let&const是创建变量的不同方式。 在早期的js中,咱们使用var关键字来创建变量。 let&const关键字是在ES6版本中引入的,其目的是在js中创建两种不同类型的变量,一种是不可变的,另一种是可变的。 const:它用于创建一个不可变变量。不可变变量是指其值在程序的整个生命周期中永不改变的变量。 let: let用于创建一个可变变量,可变变量是像var这样的普通变量,可以任意次数地更改。 2. JS 中的主要有哪几类错误JS有三类的错误: 加载时错误:加载web页面时出现的错误(如语法错误)称为加载时错误,它会动态生成错误。 运行时错误:由于滥用HTML语言中的命令而导致的错误。 逻辑错误:这些错误是由于对具有不同操作的函数执行了错误的逻辑而导致的 3. 如何通过类别名获取 dom 元素在 JS 中使用document.getElementsByClassName() 方法来获取具有类名的元素。 4.JS的作用域链是什么及其作用一般情况下,变量取值到创建这个变量的函数的作用域中取值。但是如果在当前作用域中没有查到值,就会向上级作用域去查,直到查到全局作用域,这么一个查找过程形成的链条就叫做作用域链。 JS中的作用域链主要用于解析变量的值。 如果没有这个,在不同的作用域内定义了许多变量,JS很难为变量选择某个值。 5.解释JS中的MUL函数MUL表示数的简单乘法。在这种技术中,将一个值作为参数传递给一个函数,而该函数将返回另一个函数,将第二个值传递给该函数,然后重复继续。例如:x*y*z可以表示为 function mul (x) { return function (y) { return function (z) { return x * y * z; } }}6.用纯JS编写一个程序来反转字符串使用内置函数:内置函数reverse()直接反转字符串。 str="jQuery";str = str.split("")str = str.reverse()str = str.join("")alert(str);首先将字符串拆分为数组,然后反转数组,最近将字符连接起来形成字符串。 使用循环:首先,计算字符串中的字符数,然后对原始字符串应用递减循环,该循环从最后一个字符开始,打印每个字符,直到count变为零。 7.JS中如何将页面重定向到另一个页面?使用 location.href:window.location.href =“https://www.onlineinterviewquestions.com/”使用 location.replace: window.location.replace(" https://www.onlineinterviewquestions.com/;");8. 列出JS中的一些设计模式:设计模式是软件设计中常见问题的通用可重用解决方案,以下是一些设计模式是: 创建模式:该模式抽象了对象实例化过程。 结构型模式:这些模式处理不同的类和对象以提供新功能。 行为模式:也称发布-订阅模式,定义了一个被观察者和多个观察者的、一对多的对象关系。 并行设计模式:这些模式处理多线程编程范例。 架构设计模式:这些模式用于处理架构设计。 ...

September 9, 2019 · 3 min · jiezi

政采云前端小报第46期

政采云前端小报第46期浏览更多往期小报,请访问: https://weekly.zoo.team 【前端词典】一文读懂单页应用和多页应用的区别 - 掘金 前言 最近看到一些人在问单页面和多页面应用的区别。因为最近在整理 Vue 相关的内容,所以也就输出这一篇短文希望可以给你一个整体的认识。 这里也会大体介绍单页应用实现的核心 —— 前端路由。 单页应用 VS 多页应用 直观对比图 单页应用( SinglePa...在JavaScript中,如何判断数组是数组? - 前端修炼 - SegmentFault 思否 少年,你不能太天真了,我们朝夕面对的这门语言,可是JavaScript呀,任何你觉得已经习以为常的东西都可能瞬间转化成一个大坑,令人百思不得其解。Node.js软肋之CPU密集型任务-InfoQ Node.js的EventLoop只考虑了I/O操作,但对于需要占用大量CPU资源的计算,显得有点儿先天不足。本文分析了Node.js不擅于...前端必看的数据可视化入门指南 这是一篇给大家提供数据可视化开发的入门指南,介绍了可视化要解决的问题和可以直接使用的工具,我将从下面几个方面给大家介绍,同时以阿里/蚂蚁的可视化团队和资源举例说明:...【第1717期】Nginx入门指南 nginx了解weekly/101.精读《持续集成 vs 持续交付 vs 持续部署》.md at v2 · dt-fe/weekly 前端精读周刊. Contribute to dt-fe/weekly development by creating an account on GitHub.网站性能优化实战(二) - 腾讯Web前端 IMWeb 团队社区 | blog | 团队博客 Web前端 腾讯IMWeb 团队社区面试官角度看应聘:问题到底出在哪?(上) 原创不易,希望能关注下我们,再顺手点个赞~~面试官角度看应聘:问题到底出在哪?(下) 原创不易,希望能在掘金上关注下我们,再顺手点个赞~~自动化 Web 性能优化分析方案 原创不易,希望能关注下我们,再顺手点个赞~~ 本文首发于政采云前端团队博客: 自动化 Web 性能优化分析方案 在构建 Web 站点的过程中,任何一个细节都有可能影响网站的访问速度。如果开发人员不了解前端性能相关知识,很多不利网站访问速度的因素会在线上形成...Javascript垃圾回收机制 ...

September 6, 2019 · 1 min · jiezi

面试必问的并发编程知识点你知道多少

前言众所周知,在Java的知识体系中,并发编程是非常重要的一环,也是面试的必问题,一个好的Java开发者是必须对并发编程这块有所了解的。而如何在并发场景中写出优良的代码,是一道绕不开的坎,也是考量一个 Java 开发者功底的关键技术。因此,不难发现 Java并发问题一直是各个大厂面试的重点之一,然而我发现很多候选人在面试时,常常表示对各种并发原理一脸懵逼,好像知道一些却又讲不清楚,最终导致面试失败。于是发奋学习,啃大部头书又发现理论太多,头疼。其实Java 的并发问题虽然内容繁杂,然而整个脉络还是很清晰的。那么接下来,一起来看看面试中会问到哪些并发的知识点。 线程池相关问题问题一:Java 中的线程池是如何实现的?问题二:创建线程池的几个核心构造参数?问题三:线程池中的线程是怎么创建的?是一开始就随着线程池的启动创建好的吗?问题四:既然提到可以通过配置不同参数创建出不同的线程池,那么 Java 中默认实现好的线程池又有哪些呢?请比较它们的异同。问题五:如何在 Java 线程池中提交线程? 线程安全和线程同步器相关问题问题一:java如何实现多线程之间的通讯和协作?问题二:什么叫线程安全?servlet是线程安全吗?问题三:同步有几种实现方法?问题四:volatile有什么用?能否用一句话说明下volatile的应用场景?问题五:请说明下java的内存模型及其工作流程。问题六:为什么代码会重排序?问题七:分析下JUC 中倒数计数器 CountDownLatch 的使用与原理?问题八:CountDownLatch 与线程的 Join 方法区别是什么?问题九:讲讲对JUC 中回环屏障 CyclicBarrier 的使用?问题十:CyclicBarrier内部的实现与 CountDownLatch 有何不同?问题十一:Semaphore 的内部实现是怎样的?问题十二:简单对比同步器实现,谈谈你的看法?问题十三:并发组件CopyOnWriteArrayList 是如何通过写时拷贝实现并发安全的 List? 内存模型相关问题问题一:什么是 Java 的内存模型,Java 中各个线程是怎么彼此看到对方的变量的?问题二:请谈谈 volatile 有什么特点,为什么它能保证变量对所有线程的可见性?问题三:既然 volatile 能够保证线程间的变量可见性,是不是就意味着基于 volatile 变量的运算就是并发安全的?问题四:请对比下 volatile 对比 Synchronized 的异同。问题五:请谈谈 ThreadLocal 是怎么解决并发安全的?问题六:很多人都说要慎用 ThreadLocal,谈谈你的理解,使用 ThreadLocal 需要注意些什么? 锁相关问题问题一:什么是可重入锁、乐观锁、悲观锁、公平锁、非公平锁、独占锁、共享锁?问题二:当一个线程进入某个对象的一个synchronized的实例方法后,其它线程是否可进入此对象的其它方法?问题三:synchronized和java.util.concurrent.locks.Lock的异同?问题四:什么是锁消除和锁粗化?问题五:乐观锁和悲观锁的理解及如何实现,有哪些实现方式?问题六:如何实现乐观锁(CAS)?如何避免ABA问题?问题七:读写锁可以用于什么应用场景?问题八:什么是可重入性,为什么说 Synchronized 是可重入锁?问题九:什么时候应该使用可重入锁?问题十:什么场景下可以使用volatile替换synchronized? 并发框架和并发队列相关问题问题一:SynchronizedMap和ConcurrentHashMap有什么区别?问题二:CopyOnWriteArrayList可以用于什么应用场景?问题三:如何让一段程序并发的执行,并最终汇总结果?问题四:任务非常多的时候,使用什么阻塞队列能获取最好的吞吐量?问题五:如何使用阻塞队列实现一个生产者和消费者模型?问题六:多读少写的场景应该使用哪个并发容器,为什么使用它?问题七:谈下对基于链表的非阻塞无界队列 ConcurrentLinkedQueue 原理的理解?问题八:ConcurrentLinkedQueue 内部是如何使用 CAS 非阻塞算法来保证多线程下入队出队操作的线程安全?问题九:基于链表的阻塞队列 LinkedBlockingQueue 原理。问题十:阻塞队列LinkedBlockingQueue 内部是如何使用两个独占锁 ReentrantLock 以及对应的条件变量保证多线程先入队出队操作的线程安全?问题十一:为什么不使用一把锁,使用两把为何能提高并发度?问题十二:基于数组的阻塞队列 ArrayBlockingQueue 原理。问题十三:ArrayBlockingQueue 内部如何基于一把独占锁以及对应的两个条件变量实现出入队操作的线程安全?问题十四:谈谈对无界优先级队列 PriorityBlockingQueue 原理?问题十五:PriorityBlockingQueue 内部使用堆算法保证每次出队都是优先级最高的元素,元素入队时候是如何建堆的,元素出队后如何调整堆的平衡的? CountDownLatch相关问题问题一:介绍一下 CountDownLatch 工作原理?问题二:CountDownLatch 和 CyclicBarrier 的区别?问题三:CountDownLatch 的使用场景?问题四:CountDownLatch 类中主要的方法? ...

September 6, 2019 · 1 min · jiezi

require时exports和moduleexports的区别你真的懂吗

面试会问require 的运行机制和缓存策略你了解吗?require 加载模块的是同步还是异步?谈谈你的理解 exports 和 module.exports 的区别是什么? require 加载模块的时候加载的究竟是什么? require提到 exports 和 module.exports 我们不得不提到 require 关键字。大家都知道 Node.js 遵循 CommonJS 规范,使用 require 关键字来加载模块。 require 重复引入问题问题:不知道小伙伴们在使用 require 引入模块的时候有没有相关,多个代码文件中多次引入相同的模块会不会造成重复呢? 因为在 C++ 中通常使用#IFNDEF等关键字来避免文件的重复引入,但是在 Node.js 中无需关心这一点,因为 Node.js 默认先从缓存中加载模块,一个模块被加载一次之后,就会在缓存中维持一个副本,如果遇到重复加载的模块会直接提取缓存中的副本,也就是说在任何时候每个模块都只在缓存中有一个实例。 require 加载模块的时候是同步还是异步?先回答问题,同步的!但是面试官要是问你为什么是同步还是异步的呢?其实这个答案并不是固定的,但是小伙伴们可以通过这几方面给面试官解释。 一个作为公共依赖的模块,当然想一次加载出来,同步更好模块的个数往往是有限的,而且 Node.js 在 require 的时候会自动缓存已经加载的模块,再加上访问的都是本地文件,产生的IO开销几乎可以忽略。require() 的缓存策略Node.js 会自动缓存经过 require 引入的文件,使得下次再引入不需要经过文件系统而是直接从缓存中读取。不过这种缓存方式是经过文件路径定位的,即使两个完全相同的文件,但是位于不同的路径下,会在缓存中维持两份。可以通过 console.log(require.cache)获取目前在缓存中的所有文件。 exports 与 module.exports 区别js文件启动时在一个 node 执行一个文件时,会给这个文件内生成一个 exports 和 module 对象,而module又有一个 exports 属性。他们之间的关系如下图,都指向一块{}内存区域。 exports = module.exports = {};看一张图理解这里更清楚: require()加载模块require()加载模块的时候我们来看一段实例代码 //koala.jslet a = '程序员成长指北';console.log(module.exports); //能打印出结果为:{}console.log(exports); //能打印出结果为:{}exports.a = '程序员成长指北哦哦'; //这里辛苦劳作帮 module.exports 的内容给改成 {a : '程序员成长指北哦哦'}exports = '指向其他内存区'; //这里把exports的指向指走//test.jsconst a = require('/koala');console.log(a) // 打印为 {a : '程序员成长指北哦哦'}看上面代码的打印结果,应该能得到这样的结论: ...

August 28, 2019 · 1 min · jiezi

前端该如何准备数据结构和算法

一、导读据我了解,前端程序员有相当一部分对“数据结构”和“算法”的基础概念都不是很清晰,这直接导致很多人在看到有关这部分的内容就会望而却步。 实际上,当你了解了“数据结构”和“算法”存在的真正意义,以及一些实际的应用场景,对它有了一个整体的认知之后,你可能会对它产生强烈的兴趣。当然,它带将带给你的收益也是相当可观的。 很多前端同学在看到“数据结构”和“算法”后会有一定的抵触心理,或者尝试去练习,但是被难倒,从而放弃。 这很大一部分原因是因为你还不够了解学习他们的意义,或者没有掌握合理的练习方法。 实际上,当你有了一定的目的性,并且有了合理的练习方法,再来学习这部分内容会变得得心应手。å在本文中,我就来分享一下我学习“数据结构”和“算法”的一些经验和方法。 后面我也会针对所有常见的数据结构和算法分类,进行全方位的梳理。 1.1 类别说明数据结构和算法的种类非常之多,拿树举例,树的种类包括:二叉树、B树、B+树、Trie树、红黑树等等,本文只选择了二叉树。 对前端来讲,没有必要对某些比较偏的类型和解法多做了解,一是浪费宝贵的时间,二是应用的不多。 本文选择的数据结构和算法的类别均是出现频率最高,以及应用最广的类别。 1.2 题目说明另外,做题时找对典型题目非常重要,可以让你更快速更高效的掌握知识,本文后面也会给出每种类型的典型题目供大家参考。 题目来源: awesome-coding-js:我的前端算法开源项目,包括我做过的题目以及详细解析leetcode剑指offer 另外,我会在后面长期更新一个前端算法的专栏,对每类数据结构和算法进行详细的讲解,敬请期待。 二、为什么要学习数据结构和算法在学习某块内容之前,我们一定要首先明确为什么要学,而不是盲目的跟风。 这将更有利于你从学习的过程中获得收益,而且会为你的学习带来动力。 首先明确一点,学习数据结构和算法不一定就是记住二叉树、堆、栈、队列等的解题方法也不是死记硬背一些题目,如果你仅仅停留在这样的表面思想,那么你学习起来会非常痛苦。 2.1 解决问题的思想计算机只是一个很冰冷的机器,你给他下发什么样的指令,它就能作出什么样的反应。 而开发工程师要做的是如何把实际的问题转化成计算机的指令,如何转化,来看看《数据结构》的经典说法: 设计出数据结构, 在施加以算法就行了。所以,很重要的一点,数据结构和算法对建立解决问题的思想非常重要。 如果说 Java 是自动档轿车,C 就是手动档吉普。数据结构呢?是变速箱的工作原理。你完全可以不知道变速箱怎样工作,就把自动档的车子从 A 开到 B,而且未必就比懂得的人慢。写程序这件事,和开车一样,经验可以起到很大作用,但如果你不知道底层是怎么工作的,就永远只能开车,既不会修车,也不能造车。如果你对这两件事都不感兴趣也就罢了,数据结构懂得用就好。但若你此生在编程领域还有点更高的追求,数据结构是绕不开的课题。2.2 面试这是非常现实的一点,也是很多前端学习数据结构和算法的原因。 一般对待算法的态度会分为以下几类: Google、Microsoft等知名外企在面试工程师时,算法是起决定性因素的,前端工程师也是一样,基本是每一轮都会考察,即使你有非常强的背景,也有可能因为一两道算法答的不好而与这样的企业失之交臂。 第二类,算法占重要因素的,国内的某些大厂在面试时,也会把数据结构和算法作为重要的参考因素,基本是面试必考,如果你达不到一定的要求,会直接挂掉。 第三类,起加分作用,很多公司不会把数据结构和算法作为硬性要求,但是也会象征性的出一些题目,当你把一道算法题答的很漂亮,这绝对是加分项。 可见,学好数据结构和算法对你跳槽更好的公司或者拿到更高的薪水,是非常重要的。 三、如何准备了解了数据结构和算法的重要性,那么究竟该用什么样的方法去准备呢? 3.1 全方位了解在学习和练习之前,你一定要对数据结构和算法做一个全方位的了解,对数据结构和算法的定义、分类做一个全面的理解,如果这部分做的不好,你在做题时将完全不知道你在做什么,从而陷入盲目寻找答案的过程,这个过程非常痛苦,而且往往收益甚微。 本文后面的章节,我会对常见的数据结构和算法做一个全方位的梳理。 3.2 分类练习当你对数据结构和算法有了一个整体的认知之后,就可以开始练习了。 注意,一定是分类练习!分类练习!分类练习!重要的事情说三遍。 我曾见过非常多的同学带着一腔热血就开始刷题了,从leetcode第一题开始,刚开始往往非常有动力,可能还会发个朋友圈或者沸点什么的????,然后就没有然后了。 因为前几题非常简单,可能会给你一定的自信,但是,按序号来的话,很快就会遇到hard。或者有的人,干脆只刷简单,先把所有的简单刷完。 但是,这样盲目的刷题,效果是非常差的,有可能你坚持下来,刷了几百道,也能有点效果,但是整个过程可能非常慢,而且效果远远没有分类练习要好。 所谓分类练习,即按每种类别练习,例如:这段时间只练习二叉树的题目,后面开始练习回溯算法的题目。 在开始练习之前,你往往还需要对这种具体的类别进行一个详细的了解,对其具体的定义、相关的概念和应用、可能出现的题目类型进行梳理,然后再开始。 3.3 定期回顾和总结在对一个类型针对练习一些题目之后,你就可以发现一定的规律,某一些题目是这样解,另一些题目是那样解...这是一个很正常的现象,每种类型的题目肯定是存在一定规律的。 这时候就可以开始对此类题目进行总结了,针对此类问题,以及其典型的题目,发现的解题方法,进行总结。当下次你再遇到这种类型的题目,你就能很快想到解题思路,从而很快的解答。 所以,当你看到一个题目,首先你要想到它属于哪种数据结构或算法,然后要想到这是一个什么类型的问题,然后是此类问题的解决方法。 如果你看到一个新的问题还不能做到上面这样,那说明你对此类题目的掌握程度还不够,你还要多花一些经历来进行练习。 当然,后面我会把我在这部分的总结分享出来,帮助大家少走一些弯路。 3.4 题目的选择关于题目来源,这里我推荐先看《剑指offer》,然后是leetcode,《剑指offer》上能找到非常多的典型题目,这对你发现和总结规律非常重要。看完再去刷leetcode你会发现更加轻松。 关于难度的选择, 这里我建议leetcode简单、中等难度即可,因为我们要做的是寻找规律,即掌握典型题目即可,当你掌握了这些规律,再去解一些hard的问题,也是可以的,只是多花些时间的问题。切忌不要一开始就在很多刁钻古怪的问题上耗费太多时间。 经过上面的方法,我在练习一段时间后,基本leetcode中等难度的问题可以在20min内AC,另外在最近跳槽的过程中,基本所有的算法问题我都能很快的手写出来,或者很快的想到解题思路。希望大家在看到我的经验和方法后也能达到这样的效果,或者做的比我更好。 四、时间复杂度和空间复杂度在开始学习之前,我们首先要搞懂时间复杂度和空间复杂度的概念,它们的高低共同决定着一段代码质量的好坏: 4.1 时间复杂度一个算法的时间复杂度反映了程序运行从开始到结束所需要的时间。把算法中基本操作重复执行的次数(频度)作为算法的时间复杂度。 没有循环语句,记作O(1),也称为常数阶。只有一重循环,则算法的基本操作的执行频度与问题规模n呈线性增大关系,记作O(n),也叫线性阶。 常见的时间复杂度有: O(1): Constant Complexity: Constant 常数复杂度O(log n): Logarithmic Complexity: 对数复杂度O(n): Linear Complexity: 线性时间复杂度O(n^2): N square Complexity 平⽅方O(n^3): N square Complexity ⽴立⽅方O(2^n): Exponential Growth 指数O(n!): Factorial 阶乘 ...

August 20, 2019 · 2 min · jiezi

大话2019前端面试题总结1期不要再问我http了

一、经典http面试题大纲1.什么是HTTP协议?★☆2.Web客户端是什么?☆3.Web服务端是什么?☆4.什么是资源?★5.MIME类型是什么?★☆6.什么是URI?★7.什么是URL?★8.什么是URN?★9.常见的HTTP方法有哪些?★☆10.常见的状态码200,206,302,304,404,501的含义?★★☆11.什么是报文?★★☆12.HTTP协议栈是怎么样的?★★★13.什么是DNS?★14.什么是端口号?★15.在浏览器地址栏输入一个HTTP的URL地址,按下回车键之后,浏览器怎么通过HTTP显示位于远端服务器中的某个简单HTML资源?★★★☆16.什么是代理?★☆17.什么是缓存?★☆18.什么是网关?★☆19.什么是隧道?★☆20.什么是Agent代理?★☆ 二、http面试题详解1.什么是HTTP协议?★☆HTTP:超文本传输协议。使用的是可靠的数据传输协议,在传输的过程中不会被损坏或产生混乱。HTTP可以从遍布全世界的Web服务器商将各种信息块迅速、便捷、可靠地搬移到人们桌面上的Web浏览器上去。 2.Web客户端是什么?☆Web客户端常见的又各大厂商的浏览器,比如微软的IE浏览器,google的chrome浏览器。 3.Web服务端是什么?☆Web服务器存储Web类容。Web服务器使用HTTP协议,被称为HTTP服务器。客户端向服务器发送HTTP请求,服务器会在HTTP响应中回送所请求的数据。 4.什么是资源?★Web资源寄宿在Web服务器上。所有能够提供Web内容的东西都是Web资源。比如静态文件,能够动态生成内容的软件程序。 5.MIME类型是什么?★☆MIME:多用途因特网邮件扩展。最初设计MIME是为了解决在不同的电子邮件系统之间搬移报文时存在的问题。HTTP采纳了它,用来描述并标记多媒体内容。MIME类型时一种文本标记,标识一种主要的对象类型和一个特定的子类型,中间由一条斜杠来分隔。如text/html,text/plain,image/ipeg。常见的MIME类型有数百个。 6.什么是URI?★URI:统一资源标识符,在世界范围内唯一标识并定位信息资源。URI有两种形式:URL和URN。 7.什么是URL?★URL:统一资源定位符。URL描述了一台特定服务器上某资源的特定位置。URL的第一部分被称为方案(scheme)。说明了访问资源所使用的协议类型。这里使用的时HTTP协议(http://)。第二部分表示服务器的因特网地址:www.cnblogs.com。其余部分指定了Web服务器上的某个资源:/jackson0714/p/algorithm_1.html。几乎所有的URLI都是URL。 8.什么是URN?★URN:统一资源名,URN是作为特定内容的唯一名称使用的,与目前的资源所在地无关。 9.常见的HTTP方法有哪些?★☆GET :从服务器向客户端发送命名资源POST: 将客户端数据发送到一个服务器网关应用程序PUT: 将来自客户端的数据存储到一个命名的服务器资源中去DELETE: 从服务器中删除命名资源HEAD: 仅发送命名资源响应中的HTTP首部  10.常见的状态码200,206,302,304,404,503的含义?★★☆   11.什么是报文?★★☆HTTP报文是由一行一行的简单的字符串组成的。HTTP报文都是纯文本,不是二进制代码。 请求报文:从Web客户端发往Web服务器的HTTP报文称为请求报文。响应报文:从Web服务器发往客户端的报文称为响应报文。 HTTP报文包含以下三个部分:起始行:报文的第一行就是起始行,在请求报文中用来说明要做些什么,在响应报文中说明出现了什么情况。如:GET /jackson0714/p/algorithm_1.html HTTP/1.1首部字段:起始行后面由零个或多个首部字段。以键值对的形式表示首部字段。键和值之间用冒号分隔。首部以一个空行结束。如Content-Type:text/html:charset=utf-8主体:首部字段空行之后就是可选的报文主体了,其中包含了所有类型的数据。请求主体中包括了要发送Web服务器的数据,响应主体中装载了要返回给客户端的数据。 12.HTTP协议栈是怎么样的?★★★HTTP是应用层协议。它把联网的细节都交给了通用、可靠的因特网传输协议TCPIP协议。HTTP网络协议栈: TCP协议: a.传输控制协议 b.无差错的数据传输 c.按序传输(数据总是会按照发送的顺序到达) d.未分段的数据流(可以在任意时刻以任意尺寸将数据发送出去) 13.什么是DNS?★域名解析服务。将主机名转换为IP地址。如将http://www.cnblogs.com/ 主机名转换为IP地址:211.137.51.78。 14.什么是端口号?★http://www.cnblogs.com:8080就是端口号。HTTP的URL中没有端口号时,可以假设默认端口号时80。有了IP地址和端口号,客户端就可以很方便地通过TCP/IP进行通信了。 15.在浏览器地址栏输入一个HTTP的URL地址,按下回车键之后,浏览器怎么通过HTTP显示位于远端服务器中的某个简单HTML资源?★★★☆(1)浏览器从URL中解析出服务器的主机名;(2)浏览器将服务器的主机名转换成服务器的IP地址;(3)浏览器将端口号(如果有的话),从URL中解析出来;(4)浏览器建立一条与Web服务器的TCP连接;(5)浏览器向服务器发送一条HTTP请求报文;(6)服务器向浏览器回送一条HTTP响应报文;(7)关闭连接,浏览器显示文档。 16.什么是代理?★☆代理是位于客户端和服务器之间的HTTP中间实体。接收所有客户端的HTTP请求,并将这些请求转发给服务器(可能会对请求进行修改之后转发)。 17.什么是缓存?★☆缓存HTTP的仓库,使常用页面的副本可以保存在离客户端更近的地方。 18.什么是网关?★☆网关是一种特殊的服务器,作为其他服务器的中间实体使用。通常用于将HTTP流量转换成其他的协议。 19.什么是隧道?★☆隧道是建立起来之后,就会在两条连接之间对原始数据进行盲转发的HTTP应用程序。常见用途是通过HTTP连接承载加密的安全套接字层(SSL)流量,这样SSL流量就可以穿过只允许Web流量通过的防火墙了。 20.什么是Agent代理?★☆用户Agent代理是代表用户发起HTTP的客户端程序。比如Web浏览器。另外有些自动发送HTTP请求并获取内容的代理,比如“网络蜘蛛”或者“Web机器人”。 如果你觉得这篇文章对你有所帮助,那就顺便点个赞吧,点赞收藏不迷路~ 黑芝麻哇,白芝麻发,黑芝麻白芝麻哇发哈! 前端哇发哈

August 19, 2019 · 1 min · jiezi

大话2019前端面试题总结2期不要再问我cookie了

一、cookie面试常见题:1.Cookie是什么?★☆2.Cookie能做什么?★☆3.Cookie是怎么分类的?★☆4.Cookie的工作原理?★★★5.Cookie是怎么存储的?★☆6.每次访问网站时,是不是将所有的cookie都发送所有的站点?★7.cookie与缓存怎么取舍?★★8.cookie的缺点?★★9.如何使用cookie?★★★ 二、cookie面试常见题参考答案:1.Cookie是什么?★☆cookie时当前识别用户,实现持久化会话的最好方式。简单点说就是服务器知道正在和哪个客户端通信,以及保持与已识别出的客户端通信。Cookie的基本思想就是让浏览器积累一组服务器特有的信息,每次访问服务器时都将这些信息提供给它。 2.Cookie能做什么?★☆对连接另一端的用户有更多的了解,并且能在用户浏览页面时对其进行跟踪。 3.Cookie是怎么分类的?★☆(1)会话cookie。临时cookie,记录了用户访问站点时的设置和偏好。用户退出浏览器时,会话cookie就被删除了。(2)持久cookie。持久cookie的生存时间更长一些;它们存储在硬盘上,浏览器退出,计算机重启时它们仍然存在。通常会用持久cookie维护某个用户会周期性访问的站点的配置文件或登录名。唯一区别就是它们的过期时间。如果设置了Discard参数或没有设置Expires或没有设置Max-Age参数则说明这个cookie就是一个会话cookie。 4.Cookie的工作原理?★★★(1)用户首次访问Web站点时,Web服务器对用户一无所知。(2)Web服务器通过Set-Cookie首部将cookie存放到浏览器中的cookie数据库中。cookie中包含了N个键值对,例如Cookie: id=“1234”。cookie中可以包含任意信息,但它们通常都只包含一个服务器为了进行跟踪而产生的独特的识别码。(3)将来用户再次访问同一站点时,浏览器会从cookie数据库中挑中那个服务器设置的cookie,并在cookie请求首部中(Cookie: id=“1234”)将其传回给服务器。(4)服务器可以通过id="1234"这个键值对来查找服务器为其访问积累的信息(购物历史、地址信息等)。注意:cookie并不仅限与ID号。很多Web服务器都会将信息直接保存在cooki中。比如Cookie: name="Tom"; phone="111-2222" 5.Cookie是怎么存储的?★☆浏览器负责存储cookie信息。不同的浏览器会以不同的方式来存储cookie。有的浏览器用cookis.txt存储。有的浏览器存储在高速缓存目录下独立的文本文件中。 6.每次访问网站时,是不是将所有的cookie都发送所有的站点?★不是,浏览器通常只向每个站点发送2~3个cookie。原因如下:(1)对所有这些cookie字节进行传输会严重降低性能。(2)cookie中包含的时服务器特有的名值对,对大部分站点来说,大多数cookie都只是无法识别的无用数据。(3)将所有的cookie发送给所有站点会引发潜在的隐私问题,那些你并不信任的站点也会获得你只想发给其他站点的信息。 7.cookie与缓存怎么取舍?★★cookie是私有的,浏览器不希望得到的cookie和其他浏览器的cookie相同。一般缓存cookie图片而不缓存文本。 8.cookie的缺点?★★存在安全隐患。第三方Web站点使用持久cookie来跟踪用户就是对cookie一种最大的滥用。将这种做法与IP地址和Referer首部信息结合在一起,这些营销公司就可以构建起相当精确的用户档案和浏览模式信息。 9.如何使用cookie?★★★  Cookie首部用在浏览器发送的request中。它会将所有与域、路径和安全过滤器相匹配的未过期cookie都发送给这个站点。所有cookie都被组合到一个cookie首部中。 Cookie: Name1=Tom; Name2=Jerry如果你觉得这篇文章对你有所帮助,那就顺便点个赞吧,点赞收藏不迷路~ 黑芝麻哇,白芝麻发,黑芝麻白芝麻哇发哈! 前端哇发哈

August 19, 2019 · 1 min · jiezi

8-道高频出现的-Vue-面试题及答案

前言本文讲解 8 道高频出现的 Vue 面试题及答案。 复习前端面试的知识,是为了巩固前端的基础知识,最重要的还是平时的积累!注意:文章的题与题之间用下划线分隔开,答案仅供参考。 前端硬核面试专题的完整版在此:前端硬核面试专题,包含:HTML + CSS + JS + ES6 + Webpack + Vue + React + Node + HTTPS + 数据结构与算法 + Git 。 Vue对 MVC、MVP 、MVVM 的理解 MVC 模式的意思是,软件可以分成三个部分。 视图(View):用户界面。控制器(Controller):业务逻辑。模型(Model):数据保存。各部分之间的通信方式如下。 View 传送指令到 ControllerController 完成业务逻辑后,要求 Model 改变状态Model 将新的数据发送到 View,用户得到反馈所有通信都是单向的(逆时针)。MVP 模式将 Controller 改名为 Presenter,同时改变了通信方向。 各部分之间的通信,都是双向的(顺时针)。View 与 Model 不发生联系,都通过 Presenter 传递。View 非常薄,不部署任何业务逻辑,称为 "被动视图"(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。MVVM 模式将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致。 ...

August 18, 2019 · 3 min · jiezi

如何通过MD5反查身份证号

题目:设计一个身份证查询系统,将身份证号md5 之后存储,输入md5值查询对应的身份证号。 要求:成本低,查询速度快设计思路:将所有可能的身份证号做一个简单的统计计算数据量根据数据量选择存储方式查询身份证生成规则:身份号码是特征组合码,由前十七位数字本体码和最后一位数字校验码组成。排列顺序从左至右依次为六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。 地址码: 表示编码对象常住户口所在县(市、旗、区)的行政区划代码。对于新生儿,该地址码为户口登记地行政区划代码。需要没说明的是,随着行政区划的调整,同一个地方进行户口登记的可能存在地址码不一致的情况。行政区划代码按GB/T2260的规定执行。 出生日期码:表示编码对象出生的年、月、日,年、月、日代码之间不用分隔符,格式为YYYYMMDD,如19880328。按GB/T 7408的规定执行。原15位身份证号码中出生日期码还有对百岁老人特定的标识,其中999、998、997、996分配给百岁老人。 顺序码: 表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。 校验码: 根据本体码,通过采用ISO 7064:1983,MOD 11-2校验码系统计算出校验码。算法可参考下文。前面有提到数字校验码,我们知道校验码也有X的,实质上为罗马字符X,相当于10. 校验码算法将本体码各位数字乘以对应加权因子并求和,除以11得到余数,根据余数通过校验码对照表查得校验码。 加权因子表: +-----------------------------------------------------------+ |位置序号|1 |2 |3 |4 |5 |6 |7 |8 |9 |10|11|12|13|14|15|16|17| +-----------------------------------------------------------+ |加权因子|7 |9 |10|5 |8 |4 |2 |1 |6 |3 |7 |9 |10|5 |8 |4 |2 | +-----------------------------------------------------------+ 校验码表: +----------------------------------------------------+ | 余数 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | +----------------------------------------------------+ | 校验码| 1 | 0 | X | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | +----------------------------------------------------+ 算法举例:本体码为11010519491231002 ...

August 18, 2019 · 1 min · jiezi

JavaScript匹配elective后的数字输出

一、问题Url 有以下三种情况: var url_1 = 'https://www.xx.cn/api?keyword=&level1=&local_batch_id=&elective=&local_province_id=33'; var url_2 = 'https://www.xx.cn/api?keyword=&level1=&local_batch_id=&elective=800&local_province_id=33'; var url_3 = 'https://www.xx.cn/api?keyword=&level1=&local_batch_id=&elective=800,700&local_province_id=33';匹配 elective 后的数字输出(写出你认为的最优解法): [] || ['800'] || ['800','700']二、答案答题可以考虑下以下几点: 效率高;可以扩展换 Url,换字段;elective 是跟在一堆空值后面,要效率较高的排除掉前面的匹配;匹配完 elective 的值之后, & 后面的匹配需要立刻停止,减少性能消耗;第三个的 Url 中带了 ,,也要考虑其他符号的可能性。2.1 方案一function getUrlValue(url){ if(!url) return; // let res = url.match(/(?<=elective=)(\d+(,\d+)*)/); // let res = /(?<=elective=)(\d+(.\d)*)/g.exec(url); let res = url.match(/(?<=elective=)(\d+(,\d+)*)/); return res ? res[0].split(',') : [];}其中:这个正则表达式 <=是零宽度断言的写法,断言 elective=有无内容,是匹配elective=的字符的,(?<=elective=) 是指匹配以elective=开头的字符串;(\d+(.\d)*)指匹配数字开头,可能不定数量逗号分隔后是数字的字符串。 2.2 方案二function getQueryFromUrl(key, url) { const matches = url.match(new RegExp(`(\\?|&)${key}=([^&]*)(&|$)`)); return !matches || matches.length <= 0 ? [] : (matches[2] ? matches[2].split(',') : []);}getQueryFromUrl('elective' , url_1)2.3 方案三IE 不支持。 ...

July 16, 2019 · 1 min · jiezi

常见的面试问题CSS已知高度写出三栏布局

问题:已知高度,写出三栏布局,其中左右两栏宽度各位200px,中间自适应 回答:效果示例解决方案(1)浮动;(2)绝对定位;(3)弹性布局;(4)表格布局;(5)网格布局。 拓展问题:(1)每个解决方案的优缺点(2)他们之间的比较,假设高度去掉,那种方法还能适用或者不适用(3)解决方案的兼容性,哪个更适用在实际项目中 拓展回答:(1)A:缺点:浮动脱离文档流,所以使用的时候要清除浮动;优点:兼容性比较好B:缺点:绝对定位布局脱离文档,它的子元素也会脱离文档流;优点:使用快捷,不容易出现问题,兼容性也比较好C:弹性布局是为了解决上述问题出现的,比较完美的一个D:表格布局比较繁琐,不利于SEO优化;表格布局兼容性比较好,IE8不支持flex,但支持表格。当其中的一个单元格超出的,两侧单元格也会同时增高,根据场景决定。E:网格布局作为一个新技术,可以实现很多复杂的布局,代码量简化很多。(2)flex布局和表格布局。浮动布局因为左侧有遮挡,所以没有超出的文本会在中间出现,超出部分没有遮挡会再左侧出现。 变通:三栏布局两栏布局左右宽度固定,中间自适应左宽度固定,右自适应上下高度固定,中间自适应右宽度固定,左自适应/上高度固定,下自适应/下高度固定,上自适应公共样式:设置大小盒子的高度为 100px,左右(left 和 right)的 div 宽度固定为 200px, 并分别给三个盒子设置不同颜色用来区分。 * { padding: 0; margin: 0;}.layout { height: 100px; margin-top: 20px; margin-bottom: 20px; overflow: hidden;}.layout div { height: 100px;}.layout .left { width: 200px; background-color: blue;}.layout .center { background-color: yellow;}.layout .right { width: 200px; background-color: red;}(1)方案一:浮动center 的 div 需要放到后面(其余方案都不需要更改 Html 顺序),对左右 div 使用 float:left 和 float:right,float 使左右两个元素脱离文档流,中间的正常文档流中。 .float .left { float: left;} .float .right { float: right;} <section class="layout"> <article class="float"> <div class="left"></div> <div class="right"></div> <div class="center"></div> </article></section>(2)方案二:绝对定位将 left、right 和 center 的 div 都设置 absolute 脱离文档流,给 center 的 div 设置左右两边距离 200px (即左右两边盒子的实际宽度)。 ...

July 15, 2019 · 1 min · jiezi

经常被面试官问道的JavaScript数据类型知识你真的懂吗

前言之前面试了几个开发者,他们确实做过不少项目,能力也是不错的,但是发现js基础不扎实, 于是决定写一下这篇javascrip数据类型相关的基础文章,其实也不仅仅是因为面试了他们,之前自己在面试的时候,也曾经被虐过,面试官说过的最深刻的一句话我到现在都记得。 基础很重要,只有基础好才会很少出bug,大多数的bug都是基础不扎实造成的。这里给出两道我们公司数据类型基础相关的面试题和答案,如果都能做对并且知道为什么(可以选择忽略本文章): //类型转换相关问题var bar=true;console.log(bar+0);console.log(bar+"xyz");console.log(bar+true);console.log(bar+false);console.log('1'>bar);console.log(1+'2'+false);console.log('2' + ['koala',1]);var obj1 = { a:1, b:2}console.log('2'+obj1);var obj2 = { toString:function(){ return 'a' }}console.log('2'+obj2)//输出结果 1 truexyz 2 1 false 12false 2koala,1 2[object Object] 2a//作用域和NaN 这里不具体讲作用域,意在说明NaNvar b=1;function outer(){ var b=2; function inner(){ b++; console.log(b); var b=3; } inner();}outer();//输出结果 NaN本篇文章会以一个面试官问问题的角度来进行分析讲解 js中的数据类型面试官:说一说javascript中有哪些数据类型?JavaScript 中共有七种内置数据类型,包括基本类型和对象类型。 基本类型基本类型分为以下六种: string(字符串)boolean(布尔值)number(数字)symbol(符号)null(空值)undefined(未定义)注意: string 、number 、boolean 和 null undefined 这五种类型统称为原始类型(Primitive),表示不能再细分下去的基本类型;symbol是ES6中新增的数据类型,symbol 表示独一无二的值,通过 Symbol 函数调用生成,由于生成的 symbol 值为原始类型,所以 Symbol 函数不能使用 new 调用;null 和 undefined 通常被认为是特殊值,这两种类型的值唯一,就是其本身。对象类型对象类型也叫引用类型,array和function是对象的子类型。对象在逻辑上是属性的无序集合,是存放各种值的容器。对象值存储的是引用地址,所以和基本类型值不可变的特性不同,对象值是可变的。 ...

July 15, 2019 · 4 min · jiezi