真实面试题积累

线程池的作用 为什么不使用自带线程池;
    线程池,--其实就是一个 容纳多个线程的容器 ,其中的线程可以反复使用,省去了频繁创建线程对象的操作 ,--无需反复创建线程而消耗过多资源。
创建销毁线程是一个非常消耗性能的。
    如果在一个jvm里创建太多的线程,可能会使系统由于过度消耗内存或“切换过度”而导致系统资源不足。为了防止资源不足,--需要采取一些办法来限制任何给定时刻处理的请求数目,尽可能减少创建和销毁线程的次数,特别是一些资源耗费比较大的线程的创建和销毁,尽量利用已有对象来进行服务。
    java自带线程池的最大线程数为Integer.MAX_VALUE,直接有多少任务来创建多少线程来执行(源码里面可以看到)会直接导致CPU使用率飙升,导致卡死等
JAVA中你了解那些锁 ;
1、悲观锁和乐观锁
悲观锁:当前线程去操作数据的时候,总是认为别的线程会去修改数据,所以每次操作数据的时候都会上锁,别的线程去操作数据的时候就会 阻塞,比如synchronized;
乐观锁:当前线程每次去操作数据的时候都认为别人不会修改,更新的时候会判断别人是否会去更新数据,通过版本来判断,如果数据被修改了就拒绝更新,例如cas是乐观锁,但是严格来说并不是锁,通过原子性来保证数据的同步,例如数据库的乐观锁,通过版本控制来实现,cas不会保证线程同步,乐观的认为在数据更新期间没有其他线程影响
总结:悲观锁适合写操作多的场景,乐观锁适合读操作多的场景,乐观锁的吞吐量会比悲观锁高  
2、公平锁和非公平锁
公平锁:有多个线程按照申请锁的顺序来获取锁,就是说,如果一个线程组里面,能够保证每个线程都能拿到锁,例如:ReentrantLock(使用的同步队列FIFO)
非公平锁:获取锁的方式是随机的,保证不了每个线程都能拿到锁,会存在有的线程饿死,一直拿不到锁,例如:synchronized,ReentrantLock
总结:非公平锁性能高于公平锁,更能重复利用CPU的时间
3、可重入锁和不可重入锁
可重入锁:也叫递归锁,在外层使用锁之后,在内层仍然可以使用,并且不会产生死锁
不可重入锁:在当前线程执行某个方法已经获取了该锁,那么在方法中尝试再次获取锁时,就会获取不到被阻塞
总结:可重入锁能一定程度的避免死锁,例如:synchronized,ReentrantLock
4、自旋锁
自旋锁:一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环,任何时刻最多只能有一个执行单元获得锁
总结:不会发生线程状态的切换,一直处于用户态,减少了线程上下文切换的消耗,缺点是循环会消耗CPU
5、共享锁和独享锁
共享锁:也叫读锁,可以查看数据,但是不能修改和删除的一种数据锁,加锁后其他的用户可以并发读取,但不能修改、增加、删除数据,该锁可被多个线程持有,用于资源数据共享
独享锁:也叫排它锁、写锁、独占锁、独享锁,该锁每一次只能被一个线程所持有,加锁后任何线程试图再次加锁都会被阻塞,直到当前线程解锁。例如:线程A对data加上排它锁后,则其他线程不能再对data加任何类型的锁,获得互斥锁的线程既能读数据又能修改数据
Nacos注册中心的作用;
服务发现和服务健康监测
动态配置服务
动态 DNS服务
服务及其元数据管理
Seata的作用;
Seata是阿里开发的一个用于微服务架构的高性能零侵入易使用的 分布式事务框架。
Seata处理一个全局事务的流程如下:
​
1.TM向TC请求发起一个全局事务,TC返回一个代表这个全局事务的XID。
​
2.XID在rpc中传播给每一个调用链中的服务。
​
3.每个RM拿到XID后向TC发起一个分支事务,TC返回一个代表这个分支事务的XID。
​
4.RM完成本地分支的业务,提交本地分支,并且报告给TC。
​
5.全局事务调用链处理完毕,TM根据有无异常向TC发起全局事务的提交或者回滚。
回滚:
​
6.假设某个RM本地事务失败。该RM自身驱动本地事务回滚,并且报告给TC。
​
7.TM检测到了某个分支事务失败,向TC发起全局事务回滚。
​
TC给每一个RM发送消息,通知它们全部回滚。
9.TC将全局事务回滚的结果发送给TM。 全局事务结束。
静态方法和实例方法的区别;
1、静态方法属于整个类所有,因此调用它不需要实例化,可以直接调用(类.静态方法())。实例方法必须先实例化,创建一个对象,才能进行调用(对象.实例方法())。
2、静态方法只能访问静态成员,不能访问实例成员;而实例方法可以访问静态成员和实例成员。
3、在程序运行期间,静态方法是一直存放在内存中,因此调用速度快,但是却占用内存。实例方法是使用完成后由回收机制自动进行回收,下次再使用必须再实例化。
4、一般来说,公共的函数、经常调用的可以写成静态方法,比如数据连接等(SqlHelper)。
springboot和ssm的区别 ;
1、在开发中,虽然springboot简化了配置,但只不过是编写的方式变得简单了,和SSM整合的方式还是有些差异;
2、使用SSM开发时,多数会选择Jsp作为视图,但是springboot不推荐使用jsp。
什么是反射;
java的动态机制 允许我们在程序运行期间获取任意类的名称 包的信息 所有属性 能调用任意对象的属性方法 并且能改变对象的属性实例化任意一个类
HasMap的底层;
jdk1.7是数组加链表 1.8后是数组链表红黑树 链表长度大于8变为红黑树 小于6变为链表
 hashmap的底层是 数组+链表
 
    在向hashMap存值时,会计算key的hash值,并根据数组的长度进行取模【默认是16】,从而确定将这个键值对放到数组的哪个位置,比如map.put("userName","zhangsan");这样就会计算userName的hash值,比如是18,接着用18和16取模,得2;那么就会在arr[2]的位置放入 userName:zhangsan这么一个键值对。
    
    hashmap中可能会出现hash冲突(hash碰撞)的情况,也就是两个key不一样,但他们的hash值一样,就会导致他们出现在数组的同一个地方,这个时候就可以通过链表的方式,将这个键值对放到数组元素对应的链表里。但使用链表可能会导致一个问题,就是链表长度过长,查询起来性能低,所以在jdk1.8的时候做了优化,就是当链表达到一定长度后就会把它转换为红黑树,从而提高查询性能。
 
    在get的时候,也是根据key计算hash值,和数组长度取模后,得到数组中的位置,如果发现这个位置挂了一个链表,那就根据key找到链表中和该key对应的键值对。
 
    hashmap的扩容,默认情况数组长度是16,负载因子是0.75,所以当数组中存入数组的长度达到12以后就会进行成倍扩容,从16变为32。扩容后就会对原有hashmap中的数据进行重新的hash取模运算,得到新的位置。所以可以根据数据量的多少,更改hashmap的默认容量,从而避免频繁扩容,导致性能降低。
​
HashMap的底层是数组怎么反映出来的;
HashMap的主干是一个Entry数组。Entry是HashMap的基本组成单元,每一个Entry包含一个key-value键值对
泛型的作用;
在集合中存储对象并在使用前进行类型转换是多么的不方便。泛型防止了那种情况的发生。它提供了编译期的类型安全,确保你只能把正确类型的对象放入集合中,避免了在运行时出现ClassCastException。
说一说线程的生命周期;
新建 就绪 运行 阻塞 死亡

技术提问 项目中的遇到哪些困难,怎么解决的? 如果自己不能解决,网上百度也不能解决怎么办?

        

  1. 困难:性能问题

    • 描述:在项目中,我们遇到了性能问题,应用响应时间变得很慢,影响了用户体验。
    • 解决方法:首先,我们使用性能分析工具(如Java VisualVM)来识别瓶颈。然后,我们优化了代码,使用缓存技术、异步处理和数据库查询优化来提升性能。最后,我们进行了基准测试以确保改进的效果。
  2. 困难:第三方库兼容性问题

    • 描述:在项目中,我们使用了一个第三方库,但在不同环境下出现了兼容性问题,导致应用崩溃或错误。
    • 解决方法:首先,我们仔细查阅文档和社区支持,尝试升级或降级库的版本。如果问题仍未解决,我们会采用替代库或自己实现相关功能。如果遇到无法解决的问题,我们会联系库的维护者或社区,寻求帮助或提交Bug报告。
  3. 困难:复杂的并发问题

    • 描述:项目中涉及复杂的并发场景,导致数据不一致或死锁等问题。
    • 解决方法:我们首先进行了代码审查,确保在并发情况下没有共享资源的竞争。然后,我们使用同步工具(如锁、信号量)来管理并发访问。如果问题仍然存在,我们会使用线程转储和日志来分析问题。如果自己无法解决,我们会请教更有经验的同事或上级,并共同探讨解决方案。
  4. 困难:安全漏洞

    • 描述:我们的应用被发现存在潜在的安全漏洞,可能受到SQL注入、跨站脚本攻击等威胁。
    • 解决方法:我们首先进行了安全漏洞评估,识别潜在风险。然后,我们对代码进行了修复,使用参数化查询、输入验证和输出编码等安全措施。此外,我们还进行了安全培训,以提高团队对安全问题的敏感性。

如果在项目中遇到无法解决的问题,即使在百度等搜索引擎上找不到答案,可以采取以下步骤:

  1. 咨询同事或上级: 请教有经验的同事或上级,分享问题并寻求他们的建议和见解。

  2. 在社区或论坛提问: 参与开发者社区或专业论坛,向其他开发者提问,可能会获得新的思路和解决方案。

  3. 深入分析和调试: 使用调试工具和日志来深入分析问题,可能会找到问题的根本原因。

  4. 考虑重构或重新设计: 如果问题非常复杂且无法解决,可能需要考虑对代码进行重构或重新设计,以避免问题的出现。

linux中你了解哪些命令,说一说?复制目录是怎么复制的 linux中的管道命令(grep)你熟悉吗

        常见的Linux命令示例:

  1. ls: 列出目录内容。
  2. cd: 切换当前工作目录。
  3. pwd: 显示当前工作目录的路径。
  4. cp: 复制文件或目录。
  5. mv: 移动文件或目录,也可用于重命名文件。
  6. rm: 删除文件或目录。
  7. mkdir: 创建目录。
  8. rmdir: 删除空目录。
  9. touch: 创建空文件或更新文件的时间戳。
  10. cat: 查看文件内容。
  11. more和less: 分页查看文件内容。
  12. echo: 在终端输出文本。
  13. ps: 显示进程状态。
  14. top: 动态显示系统进程状态。
  15. kill: 终止进程。
  16. chmod: 修改文件权限。
  17. chown: 修改文件的所有者和所属组。
  18. df: 显示磁盘空间使用情况。
  19. du: 显示文件或目录的磁盘使用情况。
  20. find: 在文件系统中搜索文件和目录。
  21. grep: 在文件中搜索匹配的文本。
  22. sed: 流式文本编辑器,用于对文本进行处理和转换。
  23. awk: 文本处理工具,用于提取和处理文本数据。
  24. tar: 压缩和解压文件。
  25. ssh: 远程登录工具。
  26. scp: 在本地主机和远程主机之间复制文件。
  27. wget: 下载文件。
  28. curl: 发送HTTP请求并获取响应。

复制目录的方法:

要复制目录及其内容,可以使用cp命令的-r选项(递归复制)。例如,要将/source/dir目录复制到/destination目录,可以执行以下命令:

cp -r /source/dir /destination

-r选项表示递归复制,它会将源目录及其所有内容复制到目标目录。

关于grep管道命令:

grep是用于在文件中搜索指定模式的命令,通常与管道一起使用,用于在输出中筛选出符合条件的行。

例如,要在一个文件中搜索包含关键词"error"的行,可以使用以下命令:

grep "error" filename

如果要在一个命令的输出中搜索,可以将该命令的输出通过管道传递给grep。例如,要查找包含关键词"error"的正在运行的进程,可以使用以下命令:

ps aux | grep "error"

这将首先列出所有正在运行的进程,然后通过管道将输出传递给grep,以便仅显示包含"error"的行。

请注意,grep支持各种选项和正则表达式,使其在文本搜索和筛选方面非常强大。

你部署过项目吗,是怎么部署的?

项目部署通常涉及以下步骤:

  1. 准备环境: 在目标服务器上准备适当的操作系统、依赖库和运行环境。这可能涉及安装所需的软件和配置。

  2. 获取代码: 从版本控制系统(如Git)中获取项目代码。可以使用命令行或图形界面工具进行操作。

  3. 构建项目: 如果项目需要编译、打包或构建,执行适当的构建步骤以生成可执行文件或部署包。

  4. 配置应用: 配置应用程序的设置,如数据库连接、API密钥等。这通常在配置文件中完成。

  5. 数据库迁移: 如果项目使用数据库,可能需要执行数据库迁移以确保数据库模式与应用程序版本匹配。

  6. 部署代码: 将构建好的代码和相关文件部署到目标服务器。可以使用FTP、SCP、rsync等工具进行文件传输。

  7. 启动应用: 在目标服务器上启动应用程序。可以使用命令行工具或服务管理工具(如systemd)来管理应用程序的生命周期。

  8. 监控和测试: 确保应用程序在部署后正常运行。进行端到端测试、性能测试和监控,以确保应用程序稳定且具有良好的性能。

  9. 反向代理和域名绑定: 如果需要,设置反向代理服务器(如Nginx或Apache)来处理流量分发和SSL加密,并将域名指向应用程序。

  10. 持续集成/持续部署(CI/CD): 如果采用CI/CD实践,部署可以自动化,每次代码提交都会触发自动构建和部署流程。

需要注意的是,不同项目可能会有不同的部署需求和步骤。部署流程可能会因技术栈、应用类型和团队实践而异。在实际项目中,可能还需要处理数据库备份、安全性、容灾等问题。

中软国际1面:

接口和抽象类的区别?

1、抽象类可以有构造方法,接口中不能有构造方法。
2、接口的方法默认是 public,所有方法在接口中不能有实现,而抽象类可以有非抽象的方法。
3、接口中除了 static、final 变量,不能有其他变量,而抽象类中则不一定。
4、一个类可以实现多个接口,但只能继承一个抽象类。接口自己本身可以通过 extends 关键字扩展多个接口。
5、接口方法默认修饰符是 public,抽象方法可以有 public、protected 和 default 这些修饰符(不能使用 private 关键字修饰!)。
6、从设计层面来说,抽象是对类的抽象,是一种模板设计,而接口是对行为的抽象,是一种行为的规范。

类之间的关系有哪些?

1.继承关系2.实现关系3.依赖关系4.关联关系5.聚合关系6.组合关系

Object类常用有哪些方法?

1、 getClass():获取类的class对象。
2、 hashCode:获取对象的hashCode值
3、 equals():比较对象是否相等,比较的是值和地址,子类可重写以自定义。
4、 clone():克隆方法。
5、 toString():如果没有重写,应用对象将打印的是地址值。
6、 notify():随机选择一个在该对象上调用wait方法的线程,解除其阻塞状态。该方法只能在同步方法或同步块内部调用。如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。
7、 notifyall():解除所有那些在该对象上调用wait方法的线程的阻塞状态。该方法只能在同步方法或同步块内部调用。如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。
8、 wait():导致线程进入等待状态,直到它被其他线程通过notify()或者notifyAll唤醒。该方法只能在同步方法中调用。如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。
9、 finalize():对象回收时调用
...

开发中遇到的运行时异常有哪些?

java.lang.NullPointerException 空指针异常 :调用了未经初始化的对象或者是不存在的对象
​
java.lang.ClassNotFoundException 指定的类找不到 :类的名称和路径加载错误;通常都是程序试图通过字符串来加载某个类时可能引发异常
​
java.lang.NumberFormatException 字符串转换为数字异常 :字符型数据中包含非数字型字符
​
java.lang.IndexOutOfBoundsException 数组下标越界异常 :常见于操作数组对象时发生
​
java.lang.IIIegalArgumentException 方法传递参数错误
​
java.lang.ClassCastException 数据类型转换异常
​
java.lang.NoClassDefFoundException 未找到类定义错误
​
SQLException SQL异常 :常见于操作数据库时的SQL语句错误
​
java.lang.InstantiationException 实例化异常
​
java.lang.NoSuchMethodException 方法不存在异常
...

重写和重载的区别?

重写(Override)是父类与子类之间的多态性,实质是对父类的函数进行重新定义,如果在子类中定义某方法与其父类有相同的名称和参数则该方法被重写,不过子类函数的访问修饰权限不能小于父类的;若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法,如需父类中原有的方法则可使用 super 关键字。

 重载(Overload)是让类以统一的方式处理不同类型数据的一种手段,实质表现就是多个具有不同的参数个数或者类型的同名函数(返回值类型可随意,不能以返回类型作为重载函数的区分标准)同时存在于同一个类中,是一个类中多态性的一种表现(调用方法时通过传递不同参数个数和参数类型来决定具体使用哪个方法的多态性)。

Java 构造方法能否被重写和重载?

 重写是子类方法重写父类的方法,重写的方法名不变,而类的构造方法名必须与类名一致,假设父类的构造方法如果能够被子类重写则子类类名必须与父类类名一致才行,所以 Java 的构造方法不能被重写的。而重载是针对同一个的,所以构造方法可以被重载

你最近做过的项目是哪个?能简单介绍一下吗?

商品秒杀模块中商品的库存你是怎样处理的?

由于参加秒杀的商品,一般都是“抢到就是赚到”,所以成功下单后却不付款的情况比较少,再加上卖家对秒杀商品的库存有严格限制,所以秒杀商品采用“下单减库存”更加合理。另外,理论上由于“下单减库存”比“预扣库存”以及涉及第三方支付的“付款减库存”在逻辑上更为简单,所以性能上更占优势。

“下单减库存”在数据一致性上,主要就是保证大并发请求时库存数据不能为负数,也就是要保证数据库中的库存字段值不能为负数,一般我们有多种解决方案:一种是在应用程序中通过事务来判断,即保证减后库存不能为负数,否则就回滚;另一种办法是直接设置数据库的字段数据为无符号整数,这样减后库存字段值小于零时会直接执行 SQL 语句来报错;再有一种就是使用 CASE WHEN 判断语句

讲一下springBoot框架? springBoot框架的优势

SpringBoot是用来简化Spring应用的初始搭建以及开发过程的全新框架,该框架使用特定方式来进行配置,从而使开发人员不再需要定义样板化的配置。

SpringBoot具有如下优势:

1.创建独立的Spring应用程序,通过mian方法进行运行。

2.内置嵌入的Tomcat,可选择部署jar文件,也可部署war文件。

3.简化Maven配置,SpringBoot的父工程帮我们管理了大量的maven依赖,我们可以不用关系版本号,只需要继承引用即可。

4.自动配置Spring,根据核心application.properties配置文件+代码注解使用,就能自动配置Spring,无需要再繁琐的去配置xml文件。

sql调优

sql优化面试题链接

对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。

查询SQL尽量不要使用select *,而是具体字段 避免在where子句中使用or来连接条件 使用varchar代替char 尽量使用数值替代字符串类型 查询尽量避免返回大量数据 使用explain分析你SQL执行计划 是否使用了索引及其扫描类型 创建name字段的索引 优化like语句: 字符串怪现象 索引不宜太多,一般5个以内 索引不适合建在有大量重复数据的字段上 where限定查询的数据 避免在索引列上使用内置函数 避免在where中对字段进行表达式操作 避免在where子句中使用!=或<>操作符 去重distinct过滤字段要少 where中使用默认值代替null

中软国际2面:

八大基本类型以及他们的默认值

序号 数据类型 存储需求 大小/位 封装类 默认值 可表示数据范围
1 byte(位) 1字节 8位 Byte 0 -128~127
2 short(短整数) 2字节 16位 Short 0 -32768~32767
3 int(整数) 4字节 32位 Integer 0 -2147483648~2147483647
4 long(长整数) 8字节 64位 Long 0 -9223372036854775808~9223372036854775807
5 float(单精度) 4字节 32位 Float 0.0f 1.4E-45~3.4028235E38
6 double(双精度) 8字节 64位 Double 0.0d 4.9E-324~1.7976931348623157E308
7 char(字符) 2字节 16位 Character 0~65535
8 boolean(布尔值) 1字节 8位 Boolean false true或false

String类常用的方法

1)、length() 返回字符串中的字符数。

eg:int a=str.length(); //str是上面例中中的str,a等于11.

2)、charAt(index) 返回字符串s中指定位置的字符

eg:char a1=str.charAt(2); //a1为'l'

3)、toUpperCase() //返回一个新字符串,其中所有字母大写

eg:String b1=str.toUpperCase(); //b1为 HELLO WORLD。

4)、toLowerCase() //返回一个新字符串,其中所有字母小写。

eg:String b2=b1.toLowerCase(); //b2为 hello world。

5)、concat(s1) //将本字符串和字符串s1连接,返回一个新字符串。等价"+"

eg:String c1=b1.concat(b2); //c1为 HELLO WORLDhello world

6)、trim() //返回一个新字符串,去掉两边的空白字符

eg:"\t Good Night \n".trim() //返回一个新字符串 Good Night。

7)、equals(s1) //如果该字符串内容等于字符串s1,返回true。

eg:b1.equals(b2) //返回false

8)、equalsIgnoreCase(s1) //如果该字符串内容等于字符串s1,返回true。不区分大小写!

eg:b1.equalsIgnoreCase(b2) //返回true

9)、compareTo(s1) //返回一个大于零、等于零、小于零的整数,表明一个字符串是否大于、等于、或小于s1.

如果 s1与 s2 相等,那么该方法返回值 0; 如果按字典顺序 s1小于 s2, 那么方法返回值小于 0;如果按字典顺序 s1大于 s2,方法返回值大于 0。

eg:s1为"abc",s2 为"abg", 那 么s1compareTo(s2)返回-4

10)、compareToIgnoreCase(s1) //和compareTo一样,除了比较是区分大小写的之外。

eg:s1为"abc",s2 为"ABg", 那 么s1compareTo(s2)返回-4

11)、startsWith(prefix) //如果字符串以特定前缀开始,返回true

eg:"Welcome to Java".startsWith("We") //返回 true.

12)、endsWith(suffix) //如果字符串以特定的后缀结束,返回 true

eg: "Welcome to java".endsWith("va") //返回 true.

13)、contains(s1) //如果s1是该字符串的子字符串,返回true

eg:"Welcome to Java".contains("to") //返回 true

14)、substring(beginIndex) //返回字符串,从特定位置beginindex开始到字符串结尾

15)、substring(beginindex,endIndex) //返回字符串从从下标beginIndex到endIndex-1的下标位置

真实面试题积累_第1张图片

16)、indexOf(ch) //返回字符串中出现第一个ch的下标,如果没有返回-1

eg:"Welcome to Java".indexOf(‘W’) //返回 0.

17)、indexOf(ch,fromIndex) //返回字符串中fromIndex之后出现的第一个ch下标,如果没有返回-1

eg:"Welcome to Java".indexOf('o', 5) //返回9.

18)、lastindexOf(ch) //返回字符串中出现最后一个ch的下标,如果没有返回-1

eg:"Welcome to Java".lastindexOf(‘o’) //返回 9.

19)、lastIndexOf(s,fromindex) //返回字符串中fromIndex之前出现的第一个ch下标,如果没有返回-1

eg:"Welcome to Java".lastindexOf('o', 5) //返回4.

20)、Integer.parselnt () //将数值型字符串转换成int数值

eg:int str1= Integer.parseInt(intString); //例如intString是字符串"123" 则结果为int型123

21)、Double.parseDouble () //将数值型字符串转换成double型数值

eg:int str2= Double.parseDouble (doubleString); //例如doubleString是字符串"123.321" 则结果为double型123.321

若要将数值转换成字符串 只需要简单的字符串连接操作符即可。

eg:String s=123+"";

StringBuilder和StringBuffer的区别

使用StringBuilder或者StringBuffer来做字符串拼接。StringBuilder是非线程安全的,效率更高。StringBuffer是线程安全的,效率低一些,但安全。,StringBuffer的append、delete、replace、length等方法前都加了synchronized关键字保证线程安全

HashMap和HashTable的区别

HashMap线程不安全,HashTable线程安全其内部使用synchronized关键字进行加锁

HashMap的底层原理?什么时候会变成红黑树

在JDK1.7的时候是数组+链表;在JDK1.8的时候是数组+链表+红黑树;当链表的长度大于8的时候,就会变为红黑树。小于6变为链表

常量和方法的命名规范

常量名一般使用大写字符下划线分割 方法首字母小写驼峰命名法

说一下SpringIoc和SpringAOP, 以及他们的底层实现原理

SpringIOC控制反转 SpringAOP面向切面编程

IOC: IOC中最基本的技术就是“反射(Reflection)”编程

AOP:动态代理;Spring采用两种方法来实现动态代理,分别是JDK动态代理技术和CGLIB动态代理技术。JDK动态代理技术要求我们实现InvocationHandler接口,当我们的代理类调用方法时,会被其invoke方法拦截,进行方法的增强,但它必须基于接口来实现。CGLIB底层采用的是字节码技术来生成代理类,也是在我们调用代理类方法时,被拦截,进行方法的增强,但它可以不基于接口来实现,而采用继承的方式来实现。

讲一下反射

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

eg:

  Class c = Class.forName("com.seleflearn.Person");

        // 使用无参构造方法创建Person的实例
        Person p = (Person) c.newInstance();

        // 设置名称和年龄
        p.setName("张三");
        p.setAge(20);
---------------------------------------
 // 得到Class
        Class c = Class.forName("com.seleflearn.Person");

        // 获取有参数构造方法,获取有参构造方法的参数类型,需要使用class形式传递
        Constructor cs = c.getConstructor(String.class, int.class);

        // 通过有参构造方法创建Person的实例
        Person p = (Person) cs.newInstance("张三", 20);

在工作种有遇到sql查询很慢的情况吗?怎样优化sql

对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。   

查询SQL尽量不要使用select *,而是具体字段
避免在where子句中使用or来连接条件
使用varchar代替char
尽量使用数值替代字符串类型
查询尽量避免返回大量数据
使用explain分析你SQL执行计划
是否使用了索引及其扫描类型
创建name字段的索引
优化like语句:
字符串怪现象
索引不宜太多,一般5个以内
索引不适合建在有大量重复数据的字段上
where限定查询的数据
避免在索引列上使用内置函数
避免在where中对字段进行表达式操作
避免在where子句中使用!=或<>操作符
去重distinct过滤字段要少
where中使用默认值代替null

说一下mybatis的缓存

一级缓存是默认开启的,是SqlSession级别的缓存, 在操作数据库时需要构造sqlSession对象,不同的sqlSession之间的缓存数据区域是互相不影响的,不同的sqlSession中的缓存是互相不能读取。

二级缓存需要手动开启,在xml中进行配置,是namespace(命名空间)级别的缓存基于多个SqlSession 可以共用二级缓存,二级缓存是跨SqlSession的。

工作中Redis搭建了集群吗?

Redis集群搭建(非常详细)_yygr的博客-CSDN博客

商城每天的访问量, 以及成交量情况

用户量不大, 访问量月均10万左右,成交量在1-2W笔订单一台服务器qps一两千 三台服务器

秒杀项目整个流程

系统初始化 把商品库存数加载到redis

  1. 每次点击秒杀按钮,先从服务器获取动态拼接而成的秒杀地址。

  2. Redis以缓存用户ID和商品ID为Key,秒杀地址为Value缓存秒杀地址

  3. 用户请求秒杀商品的时候,要带上秒杀地址进行校验

  4. 防止恶意脚本抢购

  5. 使请求时间分散

收到请求 redis原子操作预减库存(在内存里加一个map,key为商品ID,value为是否有库存,这样当库存没有之后,直接通过内存中的值判断是否还有库存,减少对Redis的访问。)库存不足 直接返回

请求入队 立即返回排队中(购买请求加入消息队列,异步下单(前端显示排队中),增强用户体验)

请求出对 生成订单 减少库存(服务端)

客户端轮询,是否秒杀成功(客户端)和4同步,得到结果刷新结果显示

接口限流防刷

使用计数法,在拦截器做限制请求频率。利用Redis缓存的有效期(以用户ID拼接Url作为key,以访问次数为value),指定缓存有效期为1秒,访问接口每次将value+1,到达阈值跳转全局异常。

优化:使用拦截器+自定义注解,减少对业务代码的侵入

1.在秒杀开始前指定的时间,Redis缓存预热,将每个sku参与秒杀的库存数保存在Redis中
 而且为了避免有人恶意访问还可以生成一个随机码,也保存在Redis中,用于验证是否为正常链接购买秒杀商品
2.在每个批次秒杀开始前,将本批次所有秒杀商品的spuid保存在布隆过滤器中,减少缓存穿透的情况
秒杀开始,用户在秒杀商品的规定时间内可以查询秒杀商品详情
​
所有秒杀商品spu查询时,都先查询布隆过滤器是否包含这个spuId,如果包含允许访问,如果不包含抛出异常,也要考虑布隆过滤器误判的情况,
​
每当业务中查询spu和sku时,都需要先检查redis中是否包含这个数据,如果包含直接从redis中获得,如果不包含再从数据库中查,但是同时也注意,查询完了要保存到Redis中,以便之后的查询直接从redis中获取,在保存到Redis时,为了减少缓存雪崩的几率,我们为每个Spu和Sku对象都添加了过期时间随机数
​
查询返回前,可以在判断一下当前时间是否在可秒杀该商品的时间段内,如果不在秒杀时间段内,抛出异常
​
只有返回了完整信息,前端才可能获得包含随机码的提交路径,否则是无法完成正常连接购买的
在用户购买秒杀商品时,保证用户登录的前提下
​
验证用户是否重复秒杀(业务要求秒杀相同商品只能购买一次),我们使用userId和skuId,向Redis中保存一个key,如果没有这个key就是用户没有秒杀过,否则发生异常提示
​
我们要保证用户购买时,这个商品有库存,减少库存后,获得剩余库存信息
​
只要剩余库存不小于0,就可以为当前用户生成订单,否则发生异常
​
生成订单直接Dubbo调用Order模块完成的生成订单的方法即可
​
订单提交后,还需要修改秒杀sku库存数和生成秒杀成功记录保存在数据库
​
但是这个业务非迫切运行,我们可以将信息发送给消息队列,削峰填谷
​
然后再编写接收消息队列的代码,完成修改秒杀库存和生成秒杀成功记录的操作
​
在控制层方法上添加注解实现Sentinel的限流,保证这个业务在非常大的并发下,也能稳定运行
​
控制器方法中还要判断用户请求路径中的随机码,是否和Redis中保存的随机码一致,防止非正常连接购买

怎么实现的权限验证

自定义权限认证
客户端向认证服务申请令牌token,成功后,携带token访问资源服务器。
​
认证服务生成token,通常使用uuid生成随机字符串,并且保存到redis中。
​
资源服务器使用filter过滤器拦截需要认证的API,并校验token。校验的大概业务如下:
​
当前api是否无需权限,根据url规格匹配。
判断当前服务调用是否是内部服务调用,根据内部服务调用的服务名和密码认证。
验证是否剔除前一次登录状态。
根据token获取用户相关信息进行认证。

数据库char和vachar有什么区别? 各自的优缺点

区别一,定长和变长
char 表示定长,长度固定,varchar表示变长,即长度可变。char如果插入的长度小于定义长度时,则用空格填充;varchar小于定义长度时,还是按实际长度存储,插入多长就存多长。
因为其长度固定,char的存取速度还是要比varchar要快得多,方便程序的存储与查找;但是char也为此付出的是空间的代价,因为其长度固定,所以会占据多余的空间,可谓是以空间换取时间效率。varchar则刚好相反,以时间换空间。
​
区别之二,存储的容量不同
对 char 来说,最多能存放的字符个数 255,和编码无关。
而 varchar 呢,最多能存放 65532 个字符。varchar的最大有效长度由最大行大小和使用的字符集确定。整体最大长度是 65,532字节。
​
优缺点:
1. char类型存储时,相比varchar类型存储效率更高,
   不需要判断字符长度,直接分配磁盘空间
   2.varchar类型,相比char类型,按需分配空间。
   选择?
2. 从原则上来讲,将来字符串长度不固定的话,选择varchar类型,
   字符串长度固定不变则选择char类型
3. 实际上我们生产中在考虑性能问题的方面,
   需要有大量插入(insert)操作的应用中,我们可以考虑使用char去代替varchar。
4. 如果我们业务中,大量是查询类操作的应用中,
   数据量级又比较大情况下,变长长度数据类型,可以考虑采用varchar,
   一方面节省空间,可以有效的减少***索引树***的高度,
   从而提高索引的优化查询的效果。

什么情况下索引会失效

1. 如果条件中有or,即使其中有条件带索引也不会使用
2. 对于多列索引,不是使用的第一部分,则不会使用索引
3. like查询是以%开头
4. 如果列类型是[字符串](https://so.csdn.net/so/search?q=字符串&spm=1001.2101.3001.7020),那一定要在条件中将数据使用引号引用起来,否则不使用索引
5. 如果mysql估计使用全表扫描要比使用索引快,则不使用索引

有使用过多线程吗?多线程实现的方式

方式一:写一个类,继承Thread类,重写run方法。

方式二:写一个类,实现Runnable接口,chonrun方法,创建线程的时候传入实现了Runnable接口的实现类。

方式三:写一个类,实现Callable接口,结合FutureTask使用,可以拿到异步处理的结果。

方式四:使用线程池创建。

MyBatis的事务了解吗?四大特性是什么, 详细说?以及事务的隔离级别

  • 事务四大属性
    
    分别是 :原子性、一致性、隔离性、持久性。
    
    1、原子性(Atomicity)
    原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。
    
    2、一致性(Consistency)
    一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。举例来说,假设用户A和用户B两者的钱加起来一共是1000,那么不管A和B之间如何转账、转几次账,事务结束后两个用户的钱相加起来应该还得是1000,这就是事务的一致性。
    
    3、隔离性(Isolation)
    隔离性是当多个用户并发访问数据库时,比如同时操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
    
    4、持久性(Durability)
    持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
    
    数据库事务的隔离级别
    
    有4个,由低到高依次为Read uncommitted(未授权读取、读未提交)、Read committed(授权读取、读已提交)、Repeatable read(可重复读取)、Serializable(可串行化),这四个级别可以逐个解决脏读、不可重复读、幻象读这几类问题。
    
    - Read uncommitted(未授权读取、读未提交): 
      如果一个事务已经开始写数据,则另外一个事务则不允许同时进行写操作,但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实现。这样就避免了更新丢失,却可能出现脏读。也就是说事务B读取到了事务A未提交的数据。
    - Read committed(授权读取、读已提交): 
      读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。该隔离级别避免了脏读,但是却可能出现不可重复读。事务A事先读取了数据,事务B紧接了更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。
    - Repeatable read(可重复读取): 
      可重复读是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,即使第二个事务对数据进行修改,第一个事务两次读到的的数据是一样的。这样就发生了在一个事务内两次读到的数据是一样的,因此称为是可重复读。读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。这样避免了不可重复读取和脏读,但是有时可能出现幻象读。(读取数据的事务)这可以通过“共享读锁”和“排他写锁”实现。
    - Serializable(可串行化): 
      提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。序列化是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻像读。 

spring注入对象的方式

set方法 构造方法 注解注入

中软一面

1.JVM的构成

类加载子系统 垃圾回收器 运行时数据区
运行时数据区:线程私有 线程共有
线程私有:程序计数器 虚拟机栈 本地方法栈
线程共有:堆 方法区

2.类加载的过程

类加载的过程分为:加载、验证、准备、解析和初始化五个阶段。

3.双亲委派的作用

通过双亲委派类加载机制,保证同一个类只能被加载一次,同时也是对类资源的一种保护

4.ArrayList和LinkList的区别

ArrayList底层是数组 查询速度快 增删速度慢 
LinkList底层是链表 查询速度慢 增删速度快

5.HaspMap的底层原理?什么时候会变为红黑树?为什么要用红黑树而不是平衡二叉树或B+Tree这些

jdk1.8之前 数组加链表 1.8之后数组链表红黑树 链表长度大于8时变红黑树 红黑树不追求“完全平衡 ”,它只会求部分达到平衡要求,降低了对旋转的要求,从而提高性能。

6.HashMap的get和put方法的实现原理

map.get(Key)的实现原理(取)
1、底层会调用key的hashcode()方法,通过hash函数将hash值转换为数组下标,通过数组下标快速定位到数组的指定位置上,如果这个位置上没有任何元素,那么返回null。

2、如果这个位置上有单向链表(该位置上有元素),那么会拿着我们get(key)中的key和单向链表中的每个节点的key进行equals,如果说所有的equals都返回false,那么这个get方法返回false。

3、只要其中有一个节点的key和参数key的equals对比的结果返回true,那么这个节点的value就是我们想要找的value,get方法返回这个value.

map.put(Key,value)的实现原理(存)
1、先将key和value封装到Node节点中

2、底层会调用key的hashcode()方法,通过hash函数将hash值转换为数组下标,下标位置上如果没有任何元素,就把该Node添加到该位置上(该下标处)

7.java线程池中,你最常用的线程池是?那自定义线程池的参数是什么?那自定义s线程默认的拒绝策略是什么?

#java自带四种线程池:固定线程数线程池 固定只有一条线程的线程池 固定频率执行的线程池 动态线程池 一般都不用 用自定义线程池
参数: 核心线程数 最大线程数 空闲线程保留时间 保留时间单位 工作阻塞队列 线程工厂 拒绝策略 
核心线程建议设置为cpu核心数*2+1
默认拒绝策略
ThreadPoolExceutor.AbortPolicy : 丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常。         ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务
ThreadPoolExecutor.CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务

8. Spring AOP的底层原理和两种动态代理技术的实现方式

SpringAOP面向切面 
底层原理:动态代理 
1.jdk动态代理:实现InvocationHandler接口 当我们的代理类调用方法时,会被其invoke方法拦截,进行方法的增强,必须基于接口来实现
2.CGLIB动态代理:底层是字节码技术生成代理类 调用方法时被invoke方法拦截进行增强 可以基于继承实现

9.如何解决循环依赖

基于缓存机制 一级缓存创建完毕的bean对象SingletonObjects 二级缓存是半成品(没有初始化属性)的bean对象EarlySingletonObject

10.Mysql和Oracle分页查询有什么区别?你能说一下oracle分页查询的语句吗?

Mysql:使用Limit关键字
MySQL 分页 (利用LIMIT关键字) 计算参数为 开始序号(startNum),要查的总条数 (totalNum)select * from stu limit m, n; //m = (startPage-1)*pageSize,n = pageSize
(1)第一个参数值m表示起始行,第二个参数表示取多少行(页面大小)
(2)m= (2-1)*10+1,n=10 ,表示 limit 11,10从11行开始,取10行,即第2页数据。
(3)m、n参数值不能在语句当中写计算表达式,写到语句之前必须计算好值。

Oracle使用rownum分页
Oracle 分页 (利用自带的rownum) 计算参数为 开始序号(startNum) , 结束序号 (endNum)select * from (
select rownum rn, a.* from (
select * from table_name order by XXX
) a
where ruwnum <= y // 结束行,y = startPage*pageSize
)
where rn > x; // 起始行,x = (startPage-1)*pageSize
(1)>= y,<= x表示从第y行(起始行)~x行(结束行) 。

(2)rownum只能比较小于,不能比较大于,因为rownum是先查询后排序的,例如你的条件为rownum>1,当查询到第一条数据,rownum为1,则不符合条件。第2、3...类似,一直不符合条件,所以一直没有返回结果。所以查询的时候需要设置别名,然后查询完成之后再通过调用别名进行大于的判断。

11.你能说一下学习课程超过三门的学生名称的查询语句吗

Select name from student s,corse c where s.id=c.id group by s.id having count(corse)>3;

中软二面:

1.说一说负载均衡?

负载均衡(Load Balance) ,简单点说就是将用户的请求平摊分配到多个服务器上运行,以达到扩展服务器带宽、增强数据处理能力、增加吞吐量、提高网络的可用性和灵活性的目的。
常见的负载均衡方式有两种:
服务端负载均衡
客户端负载均衡

负载均衡算法

(1)轮转调度(Round-Robin Scheduling)算法 (2)加权轮转调度(Weighted Round-Robin Scheduling)算法 (3)随机均衡调度(Random Scheduling)算法 (4)加权随机均衡调度(Weighted Random Scheduling)算法 (5)最小连接调度(Least-Connection Scheduling)算法 (6)加权最小连接调度(Weighted Least-Connection Scheduling)算法 (7)目标地址散列调度(Destination Hashing Scheduling)算法 (8)源地址散列调度(Source Hashing Scheduling)算法 (9)基于局部性的最少链接调度(Locality-Based Least ConnectionsScheduling)算法 (10)带复制的基于局部性最少链接调度(Locality-Based Least Connectionswith Replication Scheduling)算法 (11)响应速度均衡调度(Response Time Scheduling)算法 (12)处理能力均衡调度(Processing Capacity Scheduling)算法 (13)DNS均衡调度(DNS Scheduling)算法

2.说一说多线程中死锁的原因?

多线程之间相互等待临界资源而造成彼此无法继续执行。(1)系统中存在多个临界资源且临界资源不可抢占;(2)每个线程需要多个临界资源才能继续执行。
 最常用的一种死锁阻止技术就是 锁排序 . 假设有 N 个线程尝试获取 M 把锁 , 就可以针对 M 把锁进行编号 (1, 2, 3...M). N 个线程尝试获取锁的时候 , 都按照固定的按编号由小到大顺序来获取锁 . 这样就可以避免环路等待 。

3.HashMap和HashTable的区别?

HashMap是线程不安全 HashTable是线程安全 底层采用Synchronize关键字加锁

4.LinkList和ArrayList有什么区别?

LinkList底层链表增删快查询慢 ArrayList底层是数组增删慢查询快

5.JVM类加载的过程?

类加载过程一共分三个阶段,第一个阶段是加载,然后是链接,最后是初始化

6.说说双亲委派?

如果一个类加载器收到一个类加载的请求,它首先不会自己加载,而是把这个请求委派给父类加载器,只有父类无法完成加载时子类加载器才会尝试加载

7.说说GC怎么实现回收?

首先判断对象是否为垃圾 两种算法 
1引用计数器法:为每个对象创建一个引用计数,有对象引用时计数器 +1,引用被释放时计数 -1,当计数器为 0 时就可以被回收。它有一个缺点不能解决循环引用的问题;
2可达性分析算法:从 GC Roots 开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是可以被回收的。

再收集清除垃圾对象
算法主要有:
A、标记清除法:最基础的收集算法,分为“标记”,“清除”二个阶段;
B、复制算法;
C、标记整理法;
D、分代收集  算法:当前JVM的垃圾收集大都采用分代收集算法。即根据对象的新老特点,采取合适的垃圾收集算法。
将Java堆对象分为新生代和老年代,在新生代中,每次收集都会有大量对象死去,故可以采用“复制算法”。
在老年代中,对象的存活率高,故可以采取“标记清除法”和“标记整理算法”。

8.sql优化通常使用什么方式?

查询SQL尽量不要使用select *,而是具体字段
避免在where子句中使用or来连接条件
使用varchar代替char
尽量使用数值替代字符串类型
查询尽量避免返回大量数据
使用explain分析你SQL执行计划
是否使用了索引及其扫描类型
创建name字段的索引
优化like语句:
字符串怪现象
索引不宜太多,一般5个以内
索引不适合建在有大量重复数据的字段上
where限定查询的数据
避免在索引列上使用内置函数
避免在where中对字段进行表达式操作
避免在where子句中使用!=或<>操作符
去重distinct过滤字段要少
where中使用默认值代替null

9.常用的数据库优化方式?

1、在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设得尽可能小。
2、使用连接(JOIN)来代替子查询(Sub-Queries)
3、使用联合(UNION)来代替手动创建的临时表
4、事务
5、锁定表
6、使用外键
7、使用索引
8、优化的查询语句

软通动力面试:

1.C++和java的区别?优缺点?使用场景?

都是面向对象的语言,都支持封装、继承和多态
Java不提供指针来直接访问内存,程序内存更加安全
Java的类是单继承的,C++支持多重继承;虽然Java的类不可以多继承,但是接口可以多继承。
Java有自动内存管理机制,不需要程序员手动释放无用内存

2.对单点登录的理解?

	单点登录SSO,说的是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任。
使用独立登录系统
	一般来说,大型应用会把授权的逻辑和用户信息的相关逻辑独立成一个应用,称为用户中心。用户中心不处理业务逻辑,只是处理用户信息的管理以及授权给第三方应用。第三方应用需要登录的时候,则把用户的登录请求转发给用户中心进行处理,用户处理完毕后返回凭证,第三方应用验证凭证,通过后就登录用户。

3.为什么使用JWT?有哪些部分组成? 怎么保证安全?

一个jwt token由三部分组成,header、payload与signature,以点隔开

1.Header(头) 作用:记录令牌类型、签名算法等 例如:{“alg":"HS256","type","JWT}

2.Payload(有效载荷)作用:携带一些用户信息 例如{"userId":"1","username":"mingzi"}

3.Signature(签名)作用:防止Token被篡改、确保安全性 例如 计算出来的签名,一个字符串
 

4.库存预警怎么实现?(问的是项目)

### 1. 定时器任务

使用Scheduled作为定时器,通过cron语法指定运行时间,每3小时运行一次

5.成员变量和局部变量的区别?

成员变量:
    1、成员变量定义在类中,在整个类中都可以被访问。
      2、成员变量随着对象的建立而建立,随着对象的消失而消失,存在于对象所在的堆内存中。
      3、成员变量有默认初始化值。
局部变量:
      1、局部变量只定义在局部范围内,如:函数内,语句内等,只在所属的区域有效。
      2、局部变量存在于栈内存中,作用的范围结束,变量空间会自动释放。
      3、局部变量没有默认初始化值 
  在使用变量时需要遵循的原则为:就近原则
  首先在局部范围找,有就使用;接着在成员位置找。

6.用自己的话说一下多态什么意思?为什么要用父类型引用要去指向子类型的对象?(类似于基于接口编程)

同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果,这就是多态性。简单的说:就是用基类的引用指向子类的对象。除了代码的复用性外,还可以解决项目中紧偶合的问题,提高程序的可扩展性

7.讲一下java中的异常处理经验

java中异常处理机制是使用try - catch语句,在catch语句中定义捕获异常后的操作,用try语句定义可能会出现异常的语句块。。也可以直接向外抛异常,并在方法声明里声明这个方法可能会跑出的异常提醒调用者做相应的异常处理
java中Throwable这个类可以被作为异常抛出的类,继承它的分为异常Exception和错误Error.
Exception表示程序需要捕捉和处理的的异常;
Error表示系统级别的错误和程序无需处理的。
我们所需要关心的是Exception. Execption可以分为java标准定义的异常和程序员自定义异常2种.
(1)一种是当程序违反了java语规则的时候,JAVA虚拟机就会将发生的错误表示为一个异常.这里语法规则指的是JAVA类库内置的语义检查。
(2)另一种情况就是JAVA允许程序员扩展这种语义检查,程序员可以创建自己的异常,并自由选择在何时用throw关键字引发异常。所有的异常都是Thowable的子类。
异常处理是与程序执行是并行的.
Try{
//可能发现异常的语句块
}catch(异常类型,e){
//发生异常时候的执行语句块
}finnally{
//不管是否发生异常都执行的语句块
}

8.什么是lambada表达式?

lamda表达式是一种函数式接口,可以使代码更加简洁。
何为函数式接口,若一个接口只包含唯一一个抽象方法,那么它就是一个函数式接口。
(参数)->{方法语句}
只有一个参数的时候参数可以不用括号;
只有一个语句的时候大括号可以不用;
只有一个语句且是return的时候可以省略return,直接写需要返回的值(表达式)

9.说几个java中函数式接口及其特点?4大核心

消费型接口 Consumer相当于只进不出;
供给型接口 Supplier相当于只出不进;
函数型接口 Function相当于有进有出,且一进一出;
断定型接口 Predicate相当于给了他参数之后,他给你返回一个true或false。

真实面试题积累_第2张图片

10.第三方SDK里面的对象怎么放到spring容器中管理(也就是怎么把别人的jar包里面的对象交给spring容器管理)?

1 xml配置在springweb项目工程web.xml中 ContextLoaderListener或者DispatcherServlet的初始参数contextConfigLocation指定spring配置文件位置,可以在该配置文件中直接定义bean,或者在该配置文件中import专门配置三方bean的xml文件。springboot工程,可以在启动类上面加注解@ImportResource。@ImportResource注解可以通过value指定需要扫描的xml文件,value是字符串数组可以指定多个xml配置文件。
2 @Configuration和@Bean
可以通过直接直接向spring容器注入bean。在开启注解扫描的情况下,在扫描的包路径中添加具有@Configuration注解的类,在该类的定义返回某个实例的方法,这个方法加上@Bean的注解,那么这个方法的返回值将注入spring容器,这个bean的名称是这个方法的名称。
3 @Import
@Import可以直接向容器中导入第三方包中bean。在开启注解扫描的情况下,可以在有@Controller,@Service,@Component,@Repository,@Configuration注解的类上面添加@Import注解,@Import注解有一个类数组类型的属性,类数组中的类有以下四种情况

11.对设计模式的理解?了解哪些设计模式?单例模式是线程安全的吗?

1、单例模式:作用:保证类只有一个实例。JDK中体现:Runtime类。
2、静态工厂模式:作用:代替构造函数创建对象,方法名比构造函数清晰。JDK中体现:Integer.valueOf、Class.forName
3、抽象工厂:作用:创建某一种类的对象。JDK中体现:Java.sql包。
4、原型模式:clone();原型模式的本质是拷贝原型来创建新的对象,拷贝是比new更快的创建对象的方法,当需要大批量创建新对象而且都是同一个类的对象的时候考虑使用原型模式。
一般的克隆只是浅拷贝(对象的hash值不一样,但是对象里面的成员变量的hash值是一样的)。有些场景需要深拷贝,这时我们就要重写clone方法,以ArrayList为例:
5、适配器模式:作用:使不兼容的接口相容。JDK中体现:InputStream、OutputStream。
6、装饰器模式:作用:为类添加新的功能,防止类继承带来的类爆炸。JDK中体现:io类、Collections、List。
7、外观模式:作用:封装一组交互类,一直对外提供接口。JDK中体现:logging包。
8、享元模式:作用:共享对象、节省内存。JDK中体现:Integer.valueOf、String常量池。
9、代理模式:作用:(1)透明调用被代理对象,无须知道复杂实现细节;(2)增加被代理类的功能;JDK中体现:动态代理。
10、迭代器模式:作用:将集合的迭代和集合本身分离。JDK中体现:Iterator
11、命令模式:作用:封装操作,使接口一致。JDK中体现:Runable、Callable、ThreadPoolExecutor。
线程安全问题 分情况

12.单例模式什么情况下线程安全?什么情况下线程不安全?

1. 静态的饿汉式单例模式是线程安全的
2. 在方法前面加synchronized的懒汉单例模式是线程安全的,但是效率低
3. 双重校验DCL模式的懒汉单例模式不是线程安全的 会重排序
4. 双重校验的volatile DCL模式是线程安全的
5. 静态内部类实现的单例模式是线程安全的

13.怎么防止表单重复提交?\

通过JavaScript屏蔽提交按钮(不推荐)
给数据库增加唯一键约束(简单粗暴):
	在数据库建表的时候在ID字段添加主键约束,用户名、邮箱、电话等字段加唯一性约束。确保数据库只可以添加一条数	 据。
	数据库加唯一性约束sql:
	alter table tableName_xxx add unique key uniq_xxx(field1, field2)
利用Session防止表单重复提交(推荐)
	实现原理:
	服务器返回表单页面时,会先生成一个subToken保存于session,并把该subToen传给表单页面。当表单提交时会带上		subToken,服务器拦截器Interceptor会拦截该请求,拦截器判断session保存的subToken和表单提交subToken是否一	致。若不一致或session的subToken为空或表单未携带subToken则不通过。

	首次提交表单时session的subToken与表单携带的subToken一致走正常流程,然后拦截器内会删除session保存的		subToken。当再次提交表单时由于session的subToken为空则不通过。从而实现了防止表单重复提交。
使用AOP自定义切入实现
	实现原理:
	自定义防止重复提交标记(@AvoidRepeatableCommit)。
	对需要防止重复提交的Congtroller里的mapping方法加上该注解。
	新增Aspect切入点,为@AvoidRepeatableCommit加入切入点。
	每次提交表单时,Aspect都会保存当前key到reids(须设置过期时间)。
	重复提交时Aspect会判断当前redis是否有该key,若有则拦截。	

14.git分区概念?它们之间怎么流转(工作流)?

Git——三大分区【工作区 / 暂存区 / 版本库】 远程仓库 工作区暂 add 暂存区 commit 版本库 push 远程仓库

15.有接触linux吗?什么系统?(答CentOS系统)基本命令?

一、目录操作
pwd				查看当前工作目录
clear 			清除屏幕
cd ~			当前用户目录
cd /			根目录
cd -			上一次访问的目录
cd ..			上一级目录
查看目录内信息
ll				查看当前目录下内容(LL的小写)
创建目录
mkdir aaa		在当前目录下创建aaa目录,相对路径;
mkdir ./bbb		在当前目录下创建bbb目录,相对路径;
mkdir /ccc		在根目录下创建ccc目录,绝对路径;
递归创建目录(会创建里面没有的目录文件夹)
mkdir -p temp/nginx 
搜索命令
find / -name 'b'		查询根目录下(包括子目录),名以b的目录和文件;
find / -name 'b*'		查询根目录下(包括子目录),名以b开头的目录和文件; 
重命名
mv 原先目录 文件的名称   mv tomcat001 tomcat 
剪切命令(有目录剪切到制定目录下,没有的话剪切为指定目录)
mv	/aaa /bbb		    将根目录下的aaa目录,移动到bbb目录下(假如没有bbb目录,则重命名为bbb);
mv	bbbb usr/bbb		将当前目录下的bbbb目录,移动到usr目录下,并且修改名称为bbb;
mv	bbb usr/aaa			将当前目录下的bbbb目录,移动到usr目录下,并且修改名称为aaa;
复制目录
cp -r /aaa /bbb			将/目录下的aaa目录复制到/bbb目录下,在/bbb目录下的名称为aaa
cp -r /aaa /bbb/aaa		将/目录下的aa目录复制到/bbb目录下,且修改名为aaa;
强制式删除指定目录
rm -rf /bbb			强制删除/目录下的bbb目录。如果bbb目录中还有子目录,也会被强制删除,不会提示;
删除目录
rm -r /bbb			普通删除。会询问你是否删除每一个文件
rmdir test01		目录的删除
查看树状目录结构
tree test01/

16.Mysql安装到linux上需要满足什么前提?

检查是否已经安装过 
服务器的防火墙mysql端口3306是否开放

17.对Mysql了解到什么程度?(杰哥讲的Mysql串讲内容都说一遍)

18.数据库性能怎么调优?

从硬件层面:cpu、内存、磁盘读写效率、网卡流量
数据库引擎
服务器操作系统 linux参数设置
数据库参数设置
数据库表的设计SQL语句的执行效率(影响最大的):慢查询是性能问题的罪魁祸首,不合理的数据库表结构设计和不合理的索引是影响数据库查询性能的重要因素;
数据库架构:高并发下读写分离、分库分表、多级缓存、搜索引擎

19.做的项目中并发大吗?遇到并发大的时候怎么处理?

1、尽量使用缓存技术,
2、同步转异步,
3、合并多个同类型请求为一个请求,
4、数据库方面,搭建数据库集群,
一、对于被频繁调用,更新频率较低的页面,可以采用HTML静态化技术
二、图片服务器分离
三、数据库集群和库表散列
      mysql主从。m-m-s-s-s...(2个主,多个从。多个从使用负载均衡。主写入数据,从读取数据)
四、缓存。众多的缓存框架
五、负载均衡。nginx,lvs,F5
六、搜索用单独的服务器,搜索框架
七、使用MQ服务器

20.并发量大怎么去保证数据同步(这个问题应该是超卖案例,分布式锁解决)?

当前主流的方案有两种:
1)Redis 的 set 加锁+lua 脚本解锁方案,至于是不是用守护线程续命可以结合自己的场景去决定,
2)Zookeeper 方案
通常情况下,对于数据的安全性要求没那么高的,可以采用 Redis 的方案,对数据安全性要求比较高的可以采用 Zookeeper 的方案。

21.对Nosql数据库有了解吗?

NoSQL,泛指非关系型的数据库

70

22.其他就是一些工作、定居、是否离职、工作经历(包装的需要注意)之类的闲聊了

软通面试2:


1.String.StringBuilder和StringBuffer有了解吗?
2.为什么不建议使用String做字符串拼接
3.equals和hashcode有了解吗?
4.equals为false,hashcode能为true吗?
5.有了解反射吗?
6.怎么进行sql调优?
7.索引类型有哪些?全文索引有使用过吗?
8.索引失效的情况?模糊查询都回导致索引失效吗?
9.redis的使用场景
10.redis使用的数据类型?
11.什么是spring?什么是springboot?
12.springboot中将对象交给容器管理的注解有了解吗?
13.如何保证消息得可靠投递?
14.使用队列遇到过哪些问题?
15.分布式事务使用了哪些?
16.微服务和传统服务得优缺点?
17.两个Integer类型赋值1,equals结果是什么?赋值200呢?
new integer(1)呢?
18.有了解过泛型吗?泛型可以用作参数列表吗?

银海面试

1.讲一哈jdk,jre,jvm以及他们的区别

jdk:java开发环境
jre:java运行环境
jvm:java虚拟机
1.三者联系:
JVM不能单独搞定class的执行,解释class的时候JVM需要调用解释所需要的类库lib。在JDK下面的的jre目录里面有两个文件夹bin和lib,在这里可以认为bin里的就是jvm,lib中则是jvm工作所需要的类库,而jvm和 lib和起来就称为jre。JVM+Lib=JRE。总体来说就是,我们利用JDK(调用JAVA API)开发了属于我们自己的JAVA程序后,通过JDK中的编译程序(javac)将我们的文本java文件编译成JAVA字节码,在JRE上运行这些JAVA字节码,JVM解析这些字节码,映射到CPU指令集或OS的系统调用。
​
2.三者区别:
a.JDK和JRE区别:在bin文件夹下会发现,JDK有javac.exe而JRE里面没有,javac指令是用来将java文件编译成class文件的,这是开发者需要的,而用户(只需要运行的人)是不需要的。JDK还有jar.exe, javadoc.exe等等用于开发的可执行指令文件。这也证实了一个是开发环境,一个是运行环境。
b.JRE和JVM区别:JVM并不代表就可以执行class了,JVM执行.class还需要JRE下的lib类库的支持,尤其是rt.jar。
​

2.你常用的集合有哪些?list集合中ArrayList和linklist的区别,你最常用的是哪个

3.Springioc是什么,有什么注入方式,最常用的注入方式是什么?说说你经常用的注解注入有哪些

4.springAop是什么?实现原理是什么,动态代理技术有哪些

5.怎么进行数据库中的优化的?mysql中有哪些索引?如果索引失效怎么办?

6.#{}和${}的区别,一般用哪个

7.==和equal的区别

8.HashMap和ConcurrentHashMap的区别,ConcurrentHashMap怎么实现线程安全的

9.你了解哪些锁,知道java中有哪些加了锁的类吗?

10.讲一讲微服务中的各个组件有什么作用

11.在项目中有没用到redis?在哪用到了?

12.讲一哈你了解的linux虚拟机的基础命令

软通动力面试:

1.以你的项目为背景,介绍你的项目详情,你在项目中的工作与贡献,并取得了什么成绩以及遇到了什么难题,是怎么解决的;

2.项目遇见的并发访问或同步控制的场景,一般是怎么解决的;

分布式锁

3.什么时候用synchronize好,什么时候用redis好;

单体项目使用synchronize 分布式项目使用redis

4.遇到多线程场景时,是怎么管理线程的;

线程池

5.平时在工作中会使用什么数据结构;

数组 链表 红黑树

6.介绍一下hasmap,谈谈你对他的理解以及应用;

7.为什么JDK1.8会修改成数组+链表+红黑树;

8.介绍一下JAVA类的加载机制;

 

9.平时用的中间件有哪些,介绍一下你对kafka的了解;

10.Redis在项目中能够解决哪些问题。

南天:

1.常用的mybatis标签及作用

一. 定义 sql 语句 select 标签 ,insert 标签 ,delete 标签 ,update 标签
二. 配置 JAVA 对象属性与查询结果集中列名对应关系:resultMap 标签
建立 SQL 查询结果字段与实体属性的映射关系信息
查询的结果集转换为 java 对象,方便进一步操作。
将结果集中的列与 java 对象中的属性对应起来并将值填充进去
三. 动态 sql 拼接:
if 标签 通常用于 WHERE 语句、UPDATE 语句、INSERT 语句中,通过判断参数值来决定是否使用某个查询条件、判断是否更新某一个字段、判断是否插入某个字段的值。
foreach 标签主要用于构建 in 条件,可在 sql 中对集合进行迭代。也常用到批量删除、添加等操作中。
属性介绍:
	collection:collection 属性的值有三个分别是 list、array、map 三	 种,分别对应的参数类型为:List、数组、map 集合。
	item :表示在迭代过程中每一个元素的别名
	index :表示在迭代过程中每次迭代到的位置(下标)
	open :前缀
	close :后缀
	separator :分隔符,表示迭代时每个元素之间以什么分隔
choose 标签
有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。MyBatis 提供了 choose 元素,按顺序判断 when 中的条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when
的条件都不满则时,则执行 otherwise 中的 sql。类似于 Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。
if 是与(and)的关系,而 choose 是或(or)的关系。
四. 格式化输出
where 标签
当 if 标签较多时,这样的组合可能会导致错误
set 标签
没有使用 if 标签时,如果有一个参数为 null,都会导致错误。当在 update 语句中使用 if 标签时,如果最后的 if 没有执行,则或导致逗号多余错误。使用 set 标签可以将动态的配置 set关键字,和剔除追加到条件末尾的任何不相关的逗号。
trim 标签
六. 定义常量及引用
sql 标签
当多种类型的查询语句的查询字段或者查询条件相同时,可以将其定义为常量,方便调用。为求