电话面试(2019.8.27)
- 自我介绍
- 在原来公司实习都做了什么
- java基本数据类型
Java语言提供了八种基本类型。六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型。 byte、short、int、long、float、double、Boolean、char - Arraylist和Linkedlist的区别
ArrayList
优点: 底层数据结构是数组,查询快,增删慢。
缺点: 线程不安全,效率高
LinkedList
优点: 底层数据结构是链表,查询慢,增删快。
缺点: 线程不安全,效率高
Vector
优点: 底层数据结构是数组,查询快,增删慢。
缺点: 线程安全,效率低 - Hashtable 和 HashMap 的区别
Hashtable是线程安全的,HashMap不是线程安全的。HashMap效率较高,Hashtable效率较低。Hashtable不允许null值,HashMap允许null值(key和value都允许) - StringBuffer 和 StringBuilder 的区别
StringBuffer 线程安全 StringBuilder 线程不安全 速度 一般情况下,速度从快到慢:StringBuilder>StringBuffer>String,这种比较是相对的,不是绝对的。 总结 (1)如果要操作少量的数据用 = String (2)单线程操作字符串缓冲区 下操作大量数据 = StringBuilder (3)多线程操作字符串缓冲区 下操作大量数据 = StringBuffer - JVM
运行流程: java程序经过一次编译之后,将java代码编译为字节码也就是class文件,然后在不同的操作系统上依靠不同的java虚拟机进行解释,最后再转换为不同平台的机器码,最终得到执行。这样我们是不是可以推演,如果要在mac系统上运行,是不是只需要安装mac java虚拟机就行了 - SpringBoot和Spring的区别
Spring Boot 是 Spring 开源组织下的子项目,是 Spring 组件一站式解决方案,主要是简化了使用 Spring 的难度,简省了繁重的配置,提供了各种启动器,开发者能快速上手。
独立运行
简化配置
自动配置
无代码生成和XML配置
应用监控
上手容易 - Spring的注入方式
Spring通过DI(依赖注入)实现IOC(控制反转),常用的注入方式主要有三种:构造方法注入,setter注入,基于注解的注入。 - Spring中Bean的种类及作用域
singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例
prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例
request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域才有效
session:对于每次HTTP Session,使用session定义的Bean豆浆产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效
globalsession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用portlet context的时候有效。同样只有在Web应用中使用Spring时,该作用域才有效
多线程的创建方式
(1)继承Thread类创建线程类通过继承Thread类创建线程类的具体步骤如下:
定义一个继承Thread类的子类,并重写该类的run()方法;
创建Thread子类的实例,即创建了线程对象;
调用该线程对象的start()方法启动线程。
(2)实现Runnable接口创建线程类
通过实现Runnable接口创建线程类的具体步骤如下:
定义Runnable接口的实现类,并重写该接口的run()方法;
创建Runnable实现类的实例,并以此实例作为Thread的target对象,即该Thread对象才是真正的线程对象。
(3)通过Callable和Future创建线程
通过Callable和Future创建线程的具体步骤如下:
创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
使用FutureTask对象作为Thread对象的target创建并启动新线程。
调用FutureTask对象的get()方法来获得子线程执行结束后的返回值其中
- 线程管理
1、线程睡眠——sleep
2、线程让步——yield
3、线程合并——join
4、设置线程的优先级 - 线程同步
- 同步方法
即有synchronized关键字修饰的方法。由于java的每个对象都有一个内置锁,当用此关键字修饰方法时,内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。
- 同步代码块
即有synchronized关键字修饰的语句块。被该关键字修饰的语句块会自动被加上内置锁,从而实现同步。
3、使用特殊域变量(volatile)实现线程同步
volatile关键字为域变量的访问提供了一种免锁机制;
使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新;
因此每次使用该域就要重新计算,而不是使用寄存器中的值;
volatile不会提供任何原子操作,它也不能用来修饰final类型的变量。
使用重入锁(Lock)实现线程同步
在JavaSE5.0中新增了一个java.util.concurrent包来支持同步。ReentrantLock类是可重入、互斥、实现了Lock接口的锁,它与使用synchronized方法和快具有相同的基本行为和语义,并且扩展了其能力。ReenreantLock类的常用方法有:
- 线程通信 .借助于Object类的wait()、notify()和notifyAll()实现通信
- 线程执行wait()后,就放弃了运行资格,处于冻结状态;
线程运行时,内存中会建立一个线程池,冻结状态的线程都存在于线程池中,notify()执行时唤醒的也是线程池中的线程,线程池中有多个线程时唤醒第一个被冻结的线程。
notifyall(), 唤醒线程池中所有线程。
- 使用Condition控制线程通信
jdk1.5中,提供了多线程的升级解决方案为:
(1)将同步synchronized替换为显式的Lock操作;
(2)将Object类中的wait(), notify(),notifyAll()替换成了Condition对象,该对象可以通过Lock锁对象获取;
(3)一个Lock对象上可以绑定多个Condition对象,这样实现了本方线程只唤醒对方线程,而jdk1.5之前,一个同步只能有一个锁,不同的同步只能用锁来区分,且锁嵌套时容易死锁。 - 使用阻塞队列(BlockingQueue)控制线程通信
BlockingQueue是一个接口,也是Queue的子接口。BlockingQueue具有一个特征:当生产者线程试图向BlockingQueue中放入元素时,如果该队列已满,则线程被阻塞;但消费者线程试图从BlockingQueue中取出元素时,如果队列已空,则该线程阻塞。程序的两个线程通过交替向BlockingQueue中放入元素、取出元素,即可很好地控制线程的通信。
线程池
合理利用线程池能够带来三个好处。
降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。- mysql常用的引擎
InnoDB
适用场景
MySQL官方对InnoDB的讲解
MyIsam
适用场景
补充:ISAM索引方法–索引顺序存取方法
Memory(也叫HEAP)堆内存嘛
Mrg_Myisam:(分表的一种方式–水平分表)
Blackhole(黑洞引擎) - 查询时的连接
内连接:inner join
从一张表中取出所有的记录去另外一张表中匹配,利用匹配条件进行匹配,成功则保留,失败则放弃
outer join
按照某一个表作为主表(表中所有记录在最后都会保留),根据条件去连接另外一张表,从而得到目标数据
外连接分为两种:左外连接(left join)、右外连接(right join)
左连接:左表是主表
右连接:右表是主表 - dubbo的原理
dubbo调用过程
0.服务容器负责启动,加载,运行服务提供者。
1.服务提供者在启动时,向注册中心注册自己提供的服务。
2.服务消费者在启动时,向注册中心订阅自己所需的服务。
3.注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
4.服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5.服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
Dubbo核心功能
- Remoting:远程通讯,提供对多种NIO框架抽象封装,包括“同步转异步”和“请求-响应”模式的信息交换方式。
- Cluster:服务框架,提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。
- Registry:服务注册,基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。
- 服务调用中没保证消息被消费
要保证消息不被重复消费,需要保证消息消费时的幂等性,保证了幂等性,重复消费了也不会造成系统异常。
幂等性,通俗的说,无论你重复请求多少次,你得确保对应的数据是不会改变的。
一条数据重复出现两次,数据库里就只有一条数据,这就保证了系统的幂等性。 - 并行和并发
并发(Concurrent),在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行。
并行(Parallel),当系统有一个以上CPU时,当一个CPU执行一个进程时,另一个CPU可以执行另一个进程,两个进程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。
- mybatis是如何防止SQL注入的
MyBatis框架作为一款半自动化的持久层框架,其SQL语句都要我们自己手动编写,这个时候当然需要防止SQL注入。其实,MyBatis的SQL是一个具有“输入+输出”的功能,类似于函数的结构,参考上面的两个例子。其中,parameterType表示了输入的参数类型,resultType表示了输出的参数类型。回应上文,如果我们想防止SQL注入,理所当然地要在输入参数上下功夫。上面代码中使用#的即输入参数在SQL中拼接的部分,传入参数后,打印出执行的SQL语句,会看到SQL是这样的:
select id, username, password, role from user where username=? and password=?
不管输入什么参数,打印出的SQL都是这样的。这是因为MyBatis启用了预编译功能,在SQL执行前,会先将上面的SQL发送给数据库进行编译;执行时,直接使用编译好的SQL,替换占位符“?”就可以了。因为SQL注入只能对编译过程起作用,所以这样的方式就很好地避免了SQL注入的问题。
【底层实现原理】MyBatis是如何做到SQL预编译的呢?其实在框架底层,是JDBC中的PreparedStatement类在起作用,PreparedStatement是我们很熟悉的Statement的子类,它的对象包含了编译好的SQL语句。这种“准备好”的方式不仅能提高安全性,而且在多次执行同一个SQL时,能够提高效率。原因是SQL已编译好,再次执行时无需再编译。
ps:感觉是凉了,有好几个都没答上来 2019-08-27 14:57
ps2:有点希望,答完以后发短信问了下通过的概率,那个人说如果过了会有人事通知你的,等了一会以为凉了的时候人事通知明天下午去那边面试,也是下午两点,今天晚上背两个小时明天上午背三个小时吧,把没记住的再记一下,这次电话面试问的挺多的,这是唯一的机会了,我一定要抓住啊。 2019-08-27 17:49
ps3:刚刚面试完出来,地方在网易滨江园区的旁边,技术和基础方面没怎么再问过我,直接就是看的项目然后问了一下项目,第一次面试技术和hr同时在旁边。技术问了原来公司项目的主要负责模块,怎么实现的,mq那一块,然后就是自己写的毕设项目登录怎么实现,流程,拦截器等等,因为去的时候只看了一下和背了一下基础知识,项目都没看一眼,好几个地方都没有答上来,真的是丢死人了,最后让我写一个单例模式的例子想半天都写错了,本来都会的啊,难受死了。然后hr开始聊天问了一些问题和基本情况,然后说还有一个面试的让我在这边等下,然后过了一会又有一个人进来和我聊天,但是好像不是负责技术的,就是聊了一下生活方面的还有就是对一些事物的看法什么的,还有家庭,住的地方,对出差和加班的看法,然后就让我问他有没有需要了解的,交流完后就说可以先回去了,他等下尽快让hr回复我。然后我就感觉估计又凉了吧,一般当面没有给出来结果的让回去等通知的。难受死了啊,好多会的没有回答上来。然后骑单车回来玲珑府吃了午饭,也不知道算不算是午饭,然后就是等着通知吧。公司挺好的,但是自己没怎么发挥好。 2019-08-28 16:03
ps4:已经可以确定是凉了,昨天下午问有结果没那边说没有,然后说大概多久出结果,直接说一个星期之内,一般这种就是委婉的拒绝了,如果没有凉还在考虑的话就会回答你一个具体的时候,比如下周一或者这周五之类的,也怪自己吧,如果去的时候看一下项目里面的东西,看一下简历上写的设计模式,也不会这么尴尬。虽然很想去不过奈何自己,就当做一次不错的面试经历吧。 2019-08-30 10:18