1.怎么判断一个端口是否被占用?
Windows:Cmd命令:
netstat -ano 查看端口信息,ctrl+shift+esc打开任务管理器,关闭端口对应的PID。
taskkill /PID <pid> /F 结束端口服务
Linux:netstat -anp | grep 8080 查看端口信息ps -ef | grep 8080
查看具体端口的信息:lsof -i :8080
kill <pid> 结束端口服务;
2.map接口的实现类有哪些?
Hashmap:当链表长度超过一定阈值(默认为8)时,会将链表转换为红黑树,
Hashmap、hashtable(支持线程同步)、treemap(根据key升序排序)
ConcurrentHashMap,Map集合键唯一,value可重复。Put时键相同会覆盖值。
3.hashmap与hashtable的区别?
Hashmap:键值能为null、非线程安全(原因:并发冲突,插入元素超过容量的范围触发扩容操作,即rehash,多线程的环境下进行put操作时会数据覆盖,导致get时出现死循环)。HashMap 的迭代器(Iterator)是快速失败的(fail-fast),即在迭代过程中,如果其他线程对 HashMap 进行结构上的修改,会抛出 ConcurrentModificationException 异常,hashtable 不会;
Hashtable:键值不能为null(存取值会空指针)、线程安全(原因:方法加synchronized锁,多线程使用同步方法来确保线程安全,会降低性能,推荐使用ConcurrentHashMap)。
4.可重入锁概念?
同一个线程多次获得同一把锁(计数器实现),线程成功获取自己持有的锁计数器递增释放锁递减;可重入锁是解决线程在同步代码块中嵌套调用同步方法时可能遇到的死锁问题,提高线程的灵活性。
可重入锁有:Synchronized、
ReentrantLock:可重入互斥锁实现 Lock 接口,公平模式下,锁按照线程请求的顺序进行获取;非公平模式下,锁的获取是无序的,lock 方法获取锁,unlock 方法释放锁。
ReentrantReadWriteLock:可重入读写锁。锁分为读锁和写锁,多个线程可以同时获取读锁,但只有一个线程可以获取写锁。
5.mysql事务
读未提交:脏读:一个事务读取另一个事务修改未提交的数据,事务回滚数据会不一致;
读已提交:不可重复读问题:多次读取同一行数据时,此时另一个线程修改并提交导致读取结果不一致;
可重复读(默认):幻读问题:多次执行同一个查询,此时另一个线程插入新数据,导致查询结果不一致,
幻读与不可重复读的区别:不可重复读主要关注的是同一行数据的变化,而幻读关注的是查询结果集的变化。
串行化:对数据加锁,保证同一时间只能有一个事务读写数据;
6.事务的基本要素?
原子性、一致性、隔离性、持久性
7.Juc包常用的类?
ConcurrentHashmap线程安全的哈希表实现,内部使用分段锁(Segment)来提高并发性能,适用于高并发的读写操作。
Lock:synchronized 、ReentrantLock提供适合各类场合的锁工具。
Executor:线程池执行任务接口。
8.mysql间歇锁?
间隙锁(Intention Lock)相当于行锁主要用于解决并发事务中的共享资源访问问题,控制事务对数据的读写,防止幻读。
- 短信验证的高可用和高扩展以及短信的安全性。
部署在多个服务器上,线程安全,加锁,限流,定义访问时间,用redis可以实现
10.并发和并行的区别,同步和异步的区别
并发:多个任务在同一个时间段内交替执行;
并行:多个任务在同一个时间点上同时执行,每个任务都有自己的处理器或计算资源;
同步:阻塞的,程序逐步执行,每一步都要等待前一步执行完成后在执行;用于执行简单的任务;
异步:非阻塞的,程序发起一个操作后不需要等待该操作的完成,而去执行其他操作;用来处理耗时的操作,或者同时执行多个任务;
11.什么情况下会出现多线程
并发任务:服务器处理多个请求,每个线程处理一个请求,并发处理;提高响应和吞吐量;
异步操作:处理耗时的代码如网络请求或文件读写;
资源共享:多线程获取数据实现数据共享;
12.创建多线程的方式
1、继承Thread类
2、实现Runnable接口
3、实现Callable接口
4、创建线程池
13.创建线程方式之间不同的区别
Runnable无返回值通过run()方法执行线程任务,Runnable 实例可以作为参数传递给 Thread 类的构造函数执行线程。
callable有返回值,通过call()方法执行线程任务,Callable 实例可以作为参数传递给 ExecutorService 的 submit(参数) 方法来提交任务执行,并返回一个 Future 对象,用于获取任务执行的结果。Future .get()
14.线程池创建线程的优点与缺点
使用ExecutorService、Callable、Future实现有返回结果的线程,线程池的具体实现实际上是依赖于ThreadPoolExecutor
优点:
1)避免线程创建和销毁的开销,提高线程重用;
2)管理线程,提高系统资源的使用率,避免资源竞争,堵塞
3)并发数控制线程数量提高系统性能。
缺点:
不管线程是否使用,线程池都会创建,可能会浪费资源
15.创建线程池的方式
1. 通过 ThreadPoolExecutor 创建的线程池; 2. 通过 Executors 创建的线程池。
16.线程池的重要参数
1.corePoolSize(核心线程数)默认为0,线程空闲时不会被回收;
2.maximumPoolSize(最大线程数)线程超过任务队列会创建非核心线程数;
3.keepAliveTime(线程空闲时间):非核心线程在空闲状态下的存活时间;
4.unit : keepAliveTime的单位;
5.workQueue(任务队列):用于存储待执行任务的阻塞队列;
6.threadFactory(线程工厂):用于创建新线程的工厂类定义线程名称优先级等。
7.handler(拒绝策略):当线程池和任务队列都已满,无法接收新的任务时,拒绝策略定义如何处理这些被拒绝的任务。
拒绝策略:
AbortPolicy(默认,直接抛出RejectedExecutionException异常)、
CallerRunsPolicy(由提交任务的线程来执行被拒绝的任务)、
DiscardPolicy(直接丢弃被拒绝的任务)、
DiscardOldestPolicy(丢弃最老的未处理任务,然后尝试重新提交)。
17.java线程的几种状态
1. 线程的5种状态
从操作系统层面上,任何线程一般都具有五种状态,即创建(new已经有了相应的内存空间和其它资源,但是还没有开始执行。)、就绪(runnable当线程启动start()方法启动)、运行(RUNNING当就绪状态的线程被调用并获得处理器资源时run()方法运行)、阻塞(BLOCKED挂起或需要执行耗时的输入输出操作时,将让出CPU并暂时中止自己的执行,进入堵塞状态。记住:阻塞被消除后是回到就绪状态,不是运行状态。)、终止(TERMINATED线程调用stop(), destory()或run()执行结束后,线程即处于死亡状态。处于死亡状态的线程不具有继续运行的能力)。
18.join和yield的区别
sleep是Thread类的静态方法,在指定的时间过去后,会自动恢复线程的执行。
wait是Object类的实例方法,通过调用相同对象上的notify()或notifyAll()方法来唤醒等待的线程。
join是实例方法,通过线程实例thread01.join()调用,当调用join()方法时,当前线程会被阻塞,直到被调用的线程执行完毕,即thread01线程先执行完在执行其他的线程;
yield是静态方法通过Thread.yield()调用,影响当前线程,让出 CPU 时间给其他线程。
19.什么是死锁,死锁产生的条件
多个进程或线程互相等待对方的资源,在得到新的资源之前不会释放自己的资源,这样就形成了循环等待,这种现象被称为死锁。
产生死锁的四大必要条件:
资源互斥:资源只有两种状态,只有可用和不可用两状态,不能同时使用,同一时刻只能被一个进程或线程使用。
占有且请求:已经得到资源的进程或线程,继续请求新的资源,并持续占有旧的资源。
资源不可剥夺:资源已经分配进程或线程后,不能被其它进程或线程强制性获取,除非资源的占有者主动释放。
环路等待:死锁发生时,系统中必定有两个或两个以上的进程或线程组成一条等待环路。
防止死锁方案:
使用synchronized锁
处理死锁的基本方法:
1.预防死锁:通过设置一些限制条件,去破坏产生死锁的必要条件
2.避免死锁:在资源分配过程中,使用某种方法避免系统进入不安全的状态,从而避免发生死锁
3.检测死锁:允许死锁的发生,但是通过系统的检测之后,采取一些措施,将死锁清除掉
4.解除死锁:该方法与检测死锁配合使用
20.线程不安全的原因
关于线程的抢占式执行,资源竞争
多个线程修改同一个变量
修改操作不是原子的
解决方案:使用synchronized锁
21.synchronized的实现原理
每个对象都有一个monitor对象(监视器锁)相当于jvm层面上的一个锁。
用法:synchronized后加对象,在方法、代码块上加synchronized关键字
- 线程之间通信原理
常见的线程间通信机制包括共享内存和消息传递;每个线程都有消息队列,线程可以把消息放入其他线程的消息队列中,来获取消息,还可以
用其他的通信机制(如管道、队列、信号量等)来实现。
23.为什么不用hashtable
Hashtable是加锁力度大,对所有的方法加锁。不支持null值存储;
常用ConcurrentHashMap
24.ConcurrentHashMap加锁原理
(1)线程安全是通过一种叫做分段锁(Segment Locking)的机制实现的。
(2)在 ConcurrentHashMap 中,读操作不需要获取锁,可以并发地执行。而写操作(包括插入、删除和更新操作)需要获取相应段的锁,以保证数据的一致性。
(3)ConcurrentHashMap将整个hash表分为多个段不同的段之间可以并发地进行操作,从而提高并发性能。
25.Jdk1.7和1.8在数据结构上有什么区别
Hashmap:1.7数据类型是数组+链表。1.8是数组+链表+红黑树当链表长度超过一定阈值(默认为8)时,会将链表转换为红黑树,提高操作的效率。
ConcurrentHashMap :1.7使用分段hash表,1.8增加了cas(扩容分段锁)缩小了锁的竞争范围。
ArrayList:1.7数组扩容是创建一个更大的数组,把数据复制到新的数组;1.8通过动态计算进行扩容,使用System.arraycopy()方法进行批量复制。
26.Redis的数据类型
String字符串:用于字符串,计数器缓存等。
List列表:有序的字符串列表。适用于消息队列、任务队列等场景。
Hash:适用于存储对象、用户属性、缓存等。
Set 唯一集合:数据去重。
Sorted Set有序集合:排行榜、范围查询。
27.消息队列(rabbitmq)的作用
作用分别是服务间解耦、实现异步通信、流量削峰。
削峰:控制消息数量,超过一定阈值则直接丢弃消息或处理
消息的丢失情况和解决方案:
1.丢失消息的场景
(1)生产者发送消息到Rabbitmq中时,Rabbitmq宕机;
(2)消息存储在队列中未持久化,RabbitMQ宕机导致消息丢失;
(3)消费者从RabbitMQ获取消息时RabbitMQ宕机;
2.解决方案
(1)confirm消息确认机制:生产者发送消息到RabbitMQ后,如果RabbitMQ收到消息会给生产者一个应答。
(2)消息持久化机制:交换机exchange持久化,队列持久化和消息持久化。
(3)ack事务机制:消费者消费完消息,通过ack机制通知RabbitMQ,RabbitMQ才把消息从内存中删除。这样能保证即使一个消费者出现问题,还有其他消费者去消费,消息不被丢失。
28.sql优化
1、建立合适的索引
2、数据批量操作
3、避免使用通配符%和_,会全表扫描
4、使用join链接表,确保链接列上有索引
5、避免使用select *,减少数据库传输的数据量
6、 用union all代替union
我们都知道sql语句使用union关键字后,可以获取排重后的数据。
而如果使用union all关键字,可以获取所有数据,包含重复的数据
29.服务器部署spring项目
把项目达成jar包
java -jar ***.jar命令前台运行spring项目
nohup java -jar ***.jar >> log.log & 后台运行spring项目
ps -ef | grep java 查询正在运行的项目的进程
kill [进程号]来杀死进行.然后再重新打包 再进行上传.
开放端口号
30.gti介绍
git是分布式的版本控制系统。
1.需要一台服务器作为代码仓库
2.每个用户电脑都是一个服务器(代码仓库),并且和代码仓库是镜像的,用户修改和获取代码都是提交到自己的服务器当中。
3.不需要网络就可以进行工作。
4.当连接网络时,用户可以选择将自己的服务器与代码仓库进行同步。
31.分布式的理解
多个服务器或节点通过网络实现并行处理任务和资源共享,提高数据访问和高并发性能。比如消息队列和缓存等;
32.jdk动态代理和cglab动态代理的区别
Jdk动态代理:通过Proxy类的newProxyInstance()方法获取代理对象和InvocationHandler的invoke()中编写代理逻辑。
Cglib动态代理:通过目标对象的子类获取代理类(通过字节码操作库实现继承关系);利用通过调用Enhancer对象的create()方法创建代理对象,使用Enhancer对象的setCallback()方法实现代理逻辑。
什么时候用cglib什么时候用jdk动态代理?
1、如果性能是关键因素,且目标对象实现了接口,代理的是接口方法可以使用jdk代理;
2、如果目标对象没有实现任何接口,代理非接口方法,相对来说jdk代理更轻量、简单一些;
- AspectJ是一个基于Java语言的AOP框架
Java语言的AOP(面向切面编程)框架(例如日志记录、事务管理等)与主要业务逻辑分离的方式,切面(Aspect)、切点(Pointcut)、通知(Advice)等;
34.spring创建对象的作用域
单例:Singleton(默认):在Spring中,默认的对象作用域是Singleton(单例)。Spring容器只会创建一个对象实例,并在之后的请求中返回同一个实例。
多例:Prototype:在Prototype作用域下,每次通过ApplicationContext.getBean()方法获取对象时,都会创建一个新的对象实例。Prototype作用域适用于那些需要频繁创建新对象的情况。
- spring创建bean的方式
静态工厂方法创建bean对象、实例工厂方法创建bean对象、FactoryBean创建bean对象
- BeanFactory和FactoryBean区别
BeanFactory是spring容器最基本的接口,他提供了spring容器的最基本方法,但是不提供具体的实现.日常我们用了spring容器就是DefaultListableBeanFactory,是BeanFactory的实现类.所以可以说BeanFactory就是spring容器,负责管理所有的bean.
FactoryBean是一个Bean,也可以用来创建Bean,他为我们提供了一个更灵活的创建Bean的方法.Factory产生的bean也是要交给spring容器管理的.
- 如果必须要用单例的就使用ThreadLocal
ThreadLocal 常见使用场景:
如上文所述,ThreadLocal 适用于如下两种场景
1、每个线程需要有自己单独的实例
2、实例需要在多个方法中共享,但不希望被多线程共享
- Mybatis中的#与$的区别
#{}占位符:是经过预编译的,是安全的,用来获取动态数据,实体对象等;
${}是字符串拼接:未经过预编译的,仅仅是取变量的值,是非安全的,存在SQL注入。用来传递一些静态参数如表名、列名等。
40.Mybatis里接口怎么与xml里的标签绑定
<!--命名空间 一般指定对应的接口的全路径-->
<mapper namespace="com.tulun.mapper.StudentMapper">
id:statementID,在同一个命名空间下具有唯一性,一般是对应接口中方法
41.hashmap底层数据结构
底层数据结构是数组+链表+红黑树
数组初始值大小为16
为什么扩大为原来的两倍,因为位运算操作,提高效率(>>右移左边补0变小,<<左移右边补0变大)
Hashmap扩容机制:
创建一个新的Entry空数组,长度是原数组的2倍。
ReHash:遍历原Entry数组,把所有的Entry重新Hash到新数组。
42.cookie和session的区别
Cookie 和 Session 是用来在客户端和服务器之间存储和维护状态信息的两种不同技术。
Cookie 是客户端存储的一小块数据,它会在客户端和服务器之间来回传递。Cookie 会被存储在浏览器的文件系统里,并且在浏览器发送请求的时候会自动携带这些数据。
Session 是在服务器端存储的一小块数据,它可以用来跟踪用户的状态。Session 数据存储在服务器端,并且由服务器端来维护。 客户端访问服务器时,服务器会根据客户端的请求来确定客户端的身份,并且为客户端分配一个session ID 。客户端每次请求时都会携带session ID ,服务器通过这个 session ID 来识别客户端并获取相应的 session 数据
1 作用范围不同,Cookie 保存在客户端(浏览器),Session 保存在服务器端。
2 存取方式的不同,Cookie 只能保存 ASCII,Session 可以存任意数据类型,一般情况下我们可以在 Session 中保持一些常用变量信息,比如说 UserId 等。
3 有效期不同,Cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般失效时间较短,客户端关闭或者 Session 超时都会失效。
4 隐私策略不同,Cookie 存储在客户端,比较容易遭到不法获取,早期有人将用户的登录名和密码存储在 Cookie 中导致信息被窃取;Session 存储在服务端,安全性相对 Cookie 要好一些。
5 存储大小不同, 单个 Cookie 保存的数据不能超过 4K,Session 可存储数据远高于 Cookie。
43.rabbitMQ介绍
Rabbitmq的作用:解耦、异步、削峰
RabbitMQ的死信队列:队列中不能被消费的消息称为死信队列。
消息成为死信的情况:
1.队列消息数量到达限制;比如队列最大只能存储10条消息,而发了11条消息,根据先进先出,最先发的消息会进入死信队列。
2.消费者拒接消费消息,basicNack/basicReject,并且不把消息重新放入原目标队列,requeue=false。
3.原队列存在消息过期设置,消息到达超时时间未被消费。
Rabbitmq的几种工作模式:
- 简单模式:一个生产者对应一个消费者
- Work模式:一个生产者对应多个消费者,但是一条消息只能有一个消费者获得消息!!!
轮询分发就是将消息队列中的消息,依次发送给所有消费者。一个消息只能被一个消费者获取。 - 发布/订阅模式:生产者将消息发给broker,由交换机将消息转发到绑定此交换机的每个队列,每个绑定交换机的队列都将接收到消息。
- 路由模式:以路由规则为导向,引导消息存入符合规则的队列中。再由队列的消费者进行消费的。
- 主题模式:与路由模式相似,但是,主题模式是一种模糊的匹配方式。
RabbitMQ中交换机有三种:fanout、direct、topic
44.字符串拼接的StringBuilder和StringBuffer的区别
StringBuilder和StringBuffer有相同的方法,但StringBuffer的每个方法上都加了synchronized锁所以是线程安全的。
使用场景:StringBuilder用于单线程,不用考虑多线程的数据安全情况。
反之用StringBuffer。
45.线程出现死锁
死锁:不同线程等待对方释放锁,从而出现死锁。线程未得到资源的释放,处于一个僵持的状态。
问题解决:在写代码时防止锁嵌套就行了。
46.线程池的创建
1、获取线程池对象
Executors.newCachedThreadPool()创建一个没有线程上限的线程池,
Executors.newFixedThreadPool(3)创建指定线程数量的线程池。
- 提交任务
线程池对象.submit(线程对象)
当核心线程和队列都满了,线程池会创建临时线程处理剩下的线程。
自定义线程池new ThreadPoolExecutor()有7个参数.
47.springboot和springcloud的优缺点
Springboot的优点:创建独立的spring程序、内嵌服务器、自动配置spring、简化开发,整合ssm框架,减少配置文件,增强程序的扩展性、业务模块分离。简化依赖关系、快速启动容器。
缺点:集成度高、spring项目转成springboot项目困难、依赖过多会导致依赖关系复杂。
Springcloud的优点:
- 服务的独立部署
每个服务都是一个独立的项目,可以独立部署,不依赖于其他服务,耦合性低
服务分离,降低耦合,兼容各种优秀框架。
- 代码的复用
每个服务都提供 REST API,所有的基础服务都必须抽出来,很多的底层实现都可以以接口方式提供。
缺点:
- 分布式部署,调用的复杂性高
- 服务和服务之间通过接口来交互,测试的难度提升
48.java常用的设计模式
单例模式:一个类只有一个实例对象
单例模式又分为如下:
1、饿汉模式:类加载时,会直接实例化单例对象,以后都返回该对象的引用。
缺点:类加载时,会直接实例化单例对象,不管是否使用到该单例对象,浪费内存。
优点:没有加锁,执行效率高,线程安全的实例。
2、懒汉模式:不要直接在类加载时实例化,而是在调用方法时,再实例化。
优点:不会占用内存
缺点:安全方面 单线程情况下,是安全的,但是在多线程下,多个线程可能同时执行singleton == null 都为true,会创建多个实例在内存中。
工厂模式:使用者和对象的生产者分离,创建对象任务交给工厂,使用者只需通过方法获得。
代理模式:
- 静态代理:
由程序员或自动生成代码,程序编译前代理类和接口就已经确定了。
- 动态代理
Jdk代理:
第一步,实现接口InvocationHandler,然后重写invoke方法,在invoke方法中调用目标对的方法。
第二步,提供一个自定义的方法,通过Proxy.newProxyInstance()得到代理对象
Cglib代理:
第一步,导入Cglib依赖(包)。
第二步,实现接口MethodInterceptor,重写intercept方法,在其中完成目标对象的方法调用。
第三步,提供自定义方法,通过工具类获取得到代理对象。
- spring的设计模式:
控制反转(Inversion of Control,IoC):Spring的核心原则之一,通过IoC容器负责对象的创建和依赖关系的管理,将对象的控制权从应用程序代码转移到框架中。IoC模式通过依赖注入(Dependency Injection,DI)实现,使得对象之间的关系更松散、可测试和可扩展。
AOP模式(Aspect-Oriented Programming):Spring通过AOP模式实现面向切面编程,将横切关注点(如日志、事务、安全等)从业务逻辑中解耦出来。Spring使用代理模式和动态代理来实现AOP,通过切面(Aspect)和连接点(Join Point)来定义和管理横切关注点。
工厂模式(Factory Pattern):Spring使用工厂模式来创建和管理Bean对象。Spring的IoC容器充当工厂,根据配置信息和需求动态创建Bean实例,隐藏对象的创建细节。
单例模式(Singleton Pattern):Spring的默认作用域是单例(Singleton),确保每个Bean只有一个实例存在。通过单例模式,Spring管理和复用Bean实例,提高性能和资源利用率。
模板模式(Template Pattern):Spring在许多模块中使用模板模式,例如JdbcTemplate、HibernateTemplate等。模板模式通过定义模板方法,将一些通用的操作封装起来,而具体实现可以由子类进行扩展和定制。
- springAop中jdk动态代理和cglib动态代理的区别
1、作用范围
Jdk只能代理接口。
Cglib代理通过继承类的方式实现,既可以代理接口又可以代理类,该类应为非final类
2、技术实现
Jdk:实现InvocationHandler+反射
Cglib:实现MethodInterceptor接口,通过修改class文件字节码来对方法增强。
- 性能
Jdk1.7以前:cglib性能高于jdk 因为chlib通过fastclass来创建类,避免使用反射。
Cglib底层有一个小而快的字节码处理框架ASM,所以性能比jdk好。
1.8后:jdk高于cglib
4、实现方式的区别
1.jdk动态代理生成的代理类和委托类实现了相同的接口;基于接口的,耦合性较低
2、cglib动态代理中生成的字节码更加复杂,生成的代理类是委托类的子类,且不能处理被final关键字修饰的方法;
3、jdk采用反射机制调用委托类的方法,cglib采用类似索引的方式直接调用委托类方法;
5、使用场景
当bean实现接口时用jdk,未实现接口时用cglib。
调用次数多时用cglib,少时用jdk
- springaop静态代理和动态代理的优缺点
静态代理优点:解决ocp开闭原则,降低耦合
缺点:当接口很多时,每个接口都需要对应的代理类,导致不好维护。
51.linux常用操作命令
cd 切换路径 ll查看列表 pwd查看所在路径 ln建立连接 cp -r复制目录内容 mv重命名 rm删除 cat打开文件 tar -cvf解压 netstat查看网络状态
52.==和equals区别
基本数据类型:==比较内容,equals不能比较
引用数据类型:==比较内存地址,未重写equals就相当于==,重写就比较内容
- 索引失效的原因
索引列上有大量重复值或空值
复合索引遵循最左前缀法则,也就是查询条件顺序和索引顺序一致
Like以%或_开头
Or前后没有同时使用索引
- mysql事务
事务特性:一致性、持久性、原子性、隔离性
事务并发性问题:
读未提交(脏读):一个事务读取另一个事务修改但未提交的数据;
读已提交(不可重复读):a事务读取数据,b事务也读取数据并修改提交,a在读取数据会不一致;
可重复读(幻读)默认:mysql读取数据会放入缓存,b事务删除数据并提交,a事务仍可以获取数据;
串行化:每个事务执行操作加上限制,一个事务执行完另一个事务才能操作,效率较低;
mysql默认是可重复读隔离级别:mysql通过mvcc实现并发控制,避免了脏读和不可重复度,mysql使用Next-Key Locking避免幻读,可以保证在同一事务中多次读取同一范围内的数据时结果是一致的;
55:rabbitMQ
解耦:消息队列新增服务不会影响功能。只需要订阅对应的主题就行了
异步:进行某个操作使用消息队列异步发送给其他服务,如果某个服务挂掉不会影响客户正常的交易流程。
削峰:在业务场景中每个时间段的处理并发量不平均,消息队列可以吧多余的请求进行存储,时间换空间,常用与突发请求的处理
流程:生产者-交换机-队列-消费者
RabbitTemplate.converAndSend(交换机名称,消息key,消息内容) 向rabbitMq发送消息
RabbitMq的config配置类:1.使用工厂进行链接2、rabbitTemplate里设置回调confirmCallBack()3、回调中有个confirm方法,有个boolean的ack(消息成功发送给mq他为true否则false)来处理发送成功或失败的消息,重发
Rabbittemplate中还可以设置消息路由失败回调通知returnCallBack来returnMessage()
消费者手动确认来获取队列中的消息
ListenerContainer来绑定队列,提交和确认方法;再使用messageListener监听队列,队列有消息会触发onMessage()获取消息内容和队列,channel.basicAck消费成功,channel.basicNack消费失败,对消费失败的进行重新派送(多次派送失败进入mq的死信队列进行特殊处理)
,返回receiver
注意:
Rabbit可以设置生产者链接mq失败重连机制
生产者消息发送confirm确认;成功返回ACK,否则NACK
消息重复:在消息发送的整个流程中某个环节出问题,会再次分派消息,要及时给中间件回馈避免消息重复,即消息接收者的消息处理是幂等性,多次重复操作获取的结果相同;
MVCC:多版本并发控制,生产者发送消息加版本号,消费者处理更新版本号
去重表:使用表的索引进行消息去重,不会插入存在的数据,插入失败的一场处理
RabbitMQ-》去重表中插入消息数据-》各个服务
56:mysql执行顺序
From
Join on
Where
Group by
Avg/sum/count
Having
Select
Distinct
Order by
57:springboot的优点
- 减少开发,自动配置和简化测试,通过注解来扫面组件
- 依赖管理,避免版本吧冲突
- 内嵌tomcat,简化部署
- 可以集成各种,如spring cloud,使我们构建微服务变得简单
58:vue相关:
59、get和post请求的区别:
get通常去获取数据,会把参数放在url中,get请求会把header和data一起发送出去;post通常提交数据,会把数据放到请求体中,post会先把header发送出去,相应成功后在发送data。
60、怎么防止sql注入
mybatis使用#{}作为占位符;
PreparedStatement具有预编译功能来固定sql语句的结构;
使用正则表达式过滤传入敏感词汇参数;
nginx反向代理屏蔽拦截参数,在nginx中配置一些特殊字符来防止sql注入;
61、css怎么画三角形
宽和高都设置为0px,通过border的交点创建三角形
62、redis的应用场景
作为Key-Value形态的内存数据库,Redis 最先会被想到的应用场景便是作为数据缓存。
Redis 中list的数据结构实现是双向链表,所以可以非常便捷的应用于消息队列(生产者 / 消费者模型)。
消息的生产者只需要通过lpush将消息放入 list,消费者便可以通过rpop取出该消息,并且可以保证消息的有序性。
63、mysql优化
(1)多个字段联合查询可以建立合适的复合索引减少回表次数,提高查询效率。
(2)for循环插入数据的时候可以进行批量插入,效率要比一个一个循环插入要高很多。
(3)可以使用缓存。
(4)当数据量比较大,代码优化也解决不了了,可以考虑分库分表。减少单表数据量过大的一个压力。
(5)尽量避免循环中操作数据库,和循环嵌套,这样对性能影响比较大。
64、前端调接口响应慢怎么解决
(1)使用缓存:缓存可以减少对数据库或其他资源的访问次数,从而加快接口响应速度。
(2)数据库优化:对于频繁查询的接口,可以通过索引、分表等方式优化数据库性能。
(3)代码优化:优化代码结构和算法,避免重复计算和不必要的循环,可以提高接口响应速度。
(4)异步处理:将一些耗时的操作异步执行,比如发送邮件、生成报表等,可以减少接口的响应时间。
(5)负载均衡:在高并发情况下,使用负载均衡可以将请求分发到多个服务器上,从而提高接口的响应速度。
65、nginx能干什么
(1)能做代理,客户端请求到代理,然后分配到各个服务器(代理功能)。
(2)负载均衡策略,根据规则随机的将请求分发到指定的服务器上处理。RR(默认):每个请求按时间顺序逐一分配到不同的后端服务器,权重。
(3)Nginx可以做服务的热部署,Nginx不停止的情况下,对Nginx进行文件升级、更新配置和更换日志文件等功能。
66、设计模式单例
单例就是单个实例,每次请求都用一个对象来处理,多例就是每次请求都重新创建一个实例对象来解决。单例模式有懒汉式,线程不安全,对象延迟加载效率高只有使用时才创建对象,首次创建效率低,代码复杂,饿汉式,对象预加载,线程安全创建好的同时对象生成,调用实例反应较快,代码简单。
多例模式为了防止并发问题。一个请求改变了对象状态,此时需要另一和对象来处理请求。对象含有可改变的转态就用多例否则就单例。
67、内链接和外链接区别
内链接是两表都满足链接条件的数据。外链接有左外链接和右外链接,包括主表所有数据子表符合连接条件的数据。
68、Springmvc流程
DispatcherServlet前端控制器接受客户端请求把请求交给处理映射器handlerMapper,handlerMapper再根据请求url找到对应的处理器Handle, DispatcherServlet再调用适配器进行具体的处理,处理器处理完请求返回model AndView,适配器将model and View返回给前端处理器,前端处理器在返回给视图解析器解析返回的model and View,解析后返回具体的View再交给DispatcherServlet
来渲染视图。
- 线程生命周期
new初始化 Runnable就绪 running运行 blocked阻塞 wait等待 sleep睡眠超时等待 dead死亡
70、什么时候使用${}
71、docker常用命令
Dockers ps 查看运行容器
Dockers ps -a 查看所有容器
Docker images 查看镜像列表
Docker rmi -f 镜像名 删除镜像
Docker run --name 容器名 -p 宿主机端口:容器端口 -d 镜像名称
Docker start 镜像名称 重启停止镜像
Docker stop 镜像名称 停止运行
- ioc原理
IOC,即控制反转,把对象的创建、初始化、销毁交给 Spring 来管理,而不是由开发者控制,实现控制反转。BeanFactory 接口实现
AOP:
(1)AOP(面向切面编程),利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得
业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
(2)通俗来说,就是不通过修改源代码方式,在主干功能里面添加新功能。
2.2 AOP的底层原理
AOP底层是使用动态代理来实现的,这里有两种情况的动态代理:
① 有接口的情况,使用 JDK 动态代理
即创建接口实现类代理对象,增强类的方法。
② 没有接口的情况,使用 CGLIB 动态代理
即创建子类的代理对象,增强类的方法。
2.3 AOP的专业术语
① 连接点:类里面可以被增强的方法,这些方法被称为连接点。
② 切入点:实际被真正增强的方法,称为切入点。
③ 通知(增强):(1)实际增强的逻辑部分称为通知(增强)
(2)通知有多种类型:前置通知、后置通知、环绕通知、异常通知、最终通知
④ 切面:把通知应用到切入点的过程,称为切面。
73、自动注入原理
在spring创建一个bean实例时,通过依赖注入方式将一些参数,属性传递到bean实例对象的过程。
74、什么时候用String,StringBuilder,StringBuffer
String:字符串改变频率不高用String如常量的声明,少量的字符串操作。
StringBuilder单线程,频繁操作比较大的字符串。
StringBuffer多线程,频繁操作比较大的字符串。
75、linux常用命令
netstat -anp | grep 8080 查看进程状态
kill -9 端口号 结束端口
pwd 查看当前所在目录
tar -cvf 打包文件
tar -xvf 解压文件
cp 复制文件
mv 移动文件
cat 查看文件
tail -f实时跟踪文件末尾内容
76、索引失效原因
select *
联合索引不满足最左匹配原则,查询条件没有遵循复合索引的字段的创建顺序。
使用索引的字段不能使用or。
使用!=。
索引列使用is null 或is not null操作符。
索引列使用函数运算符如SUBSTR。
索引列上有大量重复值或null值。
- sql优化
避免使用select *。
避免使用子查询、改为多次查询。
避免循环中频繁操作数据库。
多次插入换成批量操作。
- nacos知识
Nacos提供了服务注册和发现、配置管理、服务路由和流量管理等功能
命名空间:1. 隔离环境2、分类管理3、权限控制
通过命名空间可以创建多个独立的环境,方便地进行配置和服务的管理。
- union all和union的区别
Union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序。
Union All:对两个结果集进行并集操作,包括重复行,不进行排序。
- 并发问题
多个线程操作同一个变量,可以是同一个数据,一个线程修改后更新到缓存中,另一个线程也修改更新,导致数据被覆盖,这就是并发问题。
- 抽象类和接口的区别
抽象类只能单继承,接口可以多继承
抽象类要被子类继承,接口要被类实现
抽象类有构造方法,接口没有构造方法
抽象类中既可以有抽象方法也可以有普通方法,接口中只能有抽象方法
抽象类可以有普通方法方法体,接口里面都是抽象方法,没有方法体
接口应用场景:类与类之前需要特定的接口进行协调,需要实现特定的多项功能,而不用考虑功能之间的关系。
抽象类应用场景:定义一些共享的方法而无需子类分别实现。
- 重载和重写的区别
重载发生在一个类中,方法名称相同,参数列表,返回值类型可以不同。
重写发生在被继承子类中,方法名,参数列表,返回值类型必须相同。
- 项目工作
84、MySQL索引失效的原因可能有以下几个方面:
1. 数据量过大:如果表中的数据量非常大,索引可能会失效,因为MySQL可能会选择不使用索引来进行查询,而是直接进行全表扫描。
2. 数据分布不均匀:如果索引列的数据分布不均匀,即某些值的重复率非常高,那么索引可能会失效,因为MySQL可能会认为全表扫描比使用索引更有效。
3. 数据类型不匹配:如果索引列的数据类型与查询条件的数据类型不匹配,索引可能会失效。例如,如果索引列是字符串类型,但查询条件是数字类型,索引可能无法被使用。
4. 索引列没有被使用:有时候,MySQL可能会选择不使用索引来进行查询,而是直接进行全表扫描。这可能是因为查询条件中包含了不适合使用索引的操作符,或者因为索引列不是查询的最左前缀。
5. 索引失效:索引本身可能出现问题,比如索引损坏或者过期。这种情况下,MySQL可能会选择不使用索引来进行查询。
85、mysql优化方案:
86、在Java中,static关键字可以用于修饰类的成员变量和方法,其作用有以下几点:
1. 静态变量:静态变量也称为类变量,它属于整个类的,而不是某个对象的。所有该类的对象共享同一个静态变量,可以通过类名直接访问。静态变量在类加载时被初始化,且只会被初始化一次。
2. 静态方法:静态方法也称为类方法,它属于整个类的,而不是某个对象的。静态方法可以直接通过类名调用,无需创建对象。通常用于工具类或者工具方法。
3. 静态代码块:静态代码块在类加载时执行,用于初始化静态变量或执行一些初始化操作。
4. 静态内部类:静态内部类是嵌套在外部类中的类,可以直接通过外部类访问,不依赖于外部类的实例。
总的来说,static关键字用于定义类级别的成员,而不是实例级别的成员,可以通过类名直接访问,而不需要创建对象。
Static的方法只能通过类名点调用,否则要创建对象来掉方法;
87、多表联查:
SELECT DISTINCT admin_name
a.*
FROM hard_admin a
JOIN hard_comment b on a.admin_name=b.`commit`
根据字段去重后查询其他字段:
select DISTINCT(content),content,commit from hard_comment
根据多个字段去重后,查询所有字段:
select * from hard_comment where id in (select max(id) from hard_comment group by content)
# AFTER:在某字段后, BEFOR:在某字段之前
88、
- http和https区别
HTTP(HyperText Transfer Protocol)和HTTPS(HyperText Transfer Protocol Secure)都是用于在网络上传输数据的协议,它们的主要区别在于安全性和加密性。
安全性: HTTP是一种非加密的协议,所有数据都是以明文形式传输的,因此容易被窃听和篡改。HTTPS通过使用 SSL/TLS 加密协议对数据进行加密,确保数据传输过程中的机密性和完整性,有效防止了数据被窃听和篡改的风险。
端口:HTTP 默认使用的端口是 80,而HTTPS 默认使用的端口是 443。
身份认证: HTTPS 对域名进行了认证,通过机构颁发的 SSL 证书来验证网站的身份。用户可以通过SSL证书验证网站的真实性,并确保正在访问的是正规网站。综上所述,HTTPS在安全性、加密性和身份认证方面比HTTP更加安全可靠。因此,对于一些重要的网站、金融应用等,建议使用HTTPS以保护数据传输的安全性。
89.mysql数据存储和对象存储
数据存储:使用表格的形式将数据存储在结构化的数据库中
对象存储:对象存储是一种非结构化的数据存储方法,将数据以对象(Object)的形式存储在存储系统中,通常以键值对的方式进行访问。
90、把一个表中的数据更新到另一个表中
91、ioc、aop、springboot、mybatis常用注解
IOC(控制反转)相关注解:
- @Component: 标记一个类为组件,让Spring进行管理。
- @Repository: 标记一个类为数据访问组件(例如DAO)。
- @Service: 标记一个类为业务逻辑组件(Service)。
- @Controller: 标记一个类为控制器组件(Controller)。
- @Autowired: 自动装配依赖,将Bean注入到另一个Bean中。
- @Value: 注入配置属性值。
AOP(面向切面编程)相关注解:
- @Aspect: 声明一个切面(Aspect)。
- @Before: 在方法调用之前执行通知。
- @After: 在方法调用之后执行通知。
- @Around: 环绕通知,可以在方法调用前后执行自定义逻辑。
- @Pointcut: 定义切点,用于指定切面的连接点。
Spring Boot相关注解:
- @SpringBootApplication: 标记一个类为Spring Boot应用程序的入口点。
- @RestController: 标记一个类为REST控制器,用于处理HTTP请求并返回REST响应。
- @RequestMapping: 定义请求的URL路径和HTTP方法与方法之间的映射关系。
- @PathVariable: 获取URL路径中的变量值。
- @RequestParam: 获取请求参数的值。
- @RequestBody: 将请求体中的内容绑定到方法参数。
- @ResponseBody: 将方法返回的对象作为HTTP响应的内容。
MyBatis相关注解:
- @Mapper: 标记一个接口为MyBatis的Mapper接口,用于数据库操作。
- @Param: 定义方法参数与SQL语句中的参数对应关系。
- 事务@Transactional常用注解,他的三个参数
当他调用一个出现异常且没有Transactional注解的话不会进行回滚;
//事务传播行为
//Propagation.REQUIRED:如果当前存在事务,则加入该事务,如果不存在事务,则创建一个新的事务。
//Propagation.REQUIRES_NEW:每次都创建新的事务,如果当前存在事务,则将其挂起。
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED, readOnly = true)
92、js作用域
全局作用域:整个 JavaScript 程序中都可访问的作用域。
函数作用域:函数作用域是在函数内部定义的变量和函数的作用域范围。
- 常用的类,包,接口
- 类:String、ArrayList、HashMap、Date、SimpleDateFormat、StringBuilder、Exception、Thread、Collections
- 包:lang、util、io、netjava.awt、Annotation
- 接口:Runnable、List、Map、Serializable、Iterator、Callable
- final、finally、finalize
Final类是不可被继承的。方法不能被子类重写。变量不能再改变。
finally块中的代码无论是否发生异常,都会被执行释放资源等。
finalize方法在对象被垃圾回收之前被调用,可以在该方法中进行资源释放和清理操作。
93、统计最长出勤天数
- 怎么确定一个方法是否是定时任务
@Scheduled(cron = "0 0 8 * * ?") // 每天上午8点执行
@Scheduled(fixedRate = 5000) // 每隔5秒执行一次
使用xxl-job
- 同步两张表数据
- 常见索引
主键索引、唯一索引、复合索引、全文索引
96、索引失效场景
使用索引列进行范围查询,(如使用大于、小于、区间等操作符)。
索引列存在大量null。
没有遵循索引最左前缀法则。
Like模糊匹配"%" 开头的模式无法有效利用索引。
97、集合扩容
ArrayList:默认初始容量为10,1.5倍扩容;
LinkedList:链表不需要初始容量,创建节点
hashMap:初始容量为16,2倍扩容;
98、arrayList和linkedList的区别
arrayList;基于数组的,查询快增删慢,通过索引可快速查找数据,插入数据要移动其他数据;
LinkedList:基于双向链表,增删效率高;
如果需要频繁进行随机访问操作,而对插入和删除操作不敏感,可以选择ArrayList。
如果需要频繁进行插入和删除操作,而对随机访问操作不敏感,可以选择LinkedList。
99、Redis缓存出现的问题
缓存击穿:热key过期,大量请求访问数据库,
(1)设置互斥锁(Mutex Lock):在缓存失效时,保证只有一个请求能够访问数据库,并把数据放入缓存中。
(2)使用空值缓存(Cache Null Value):如果查询数据不存在,将空结果存入缓存,并设置较短的过期时间,避免无效的请求频繁访问数据库。
缓存穿透:大量请求访问缓存中不存在的数据
(1)可以对请求参数进行合法性校验,过滤非法请求。
(2)可以将空结果缓存一段时间,避免频繁查询数据库。
缓存雪崩:大量的key同时过期;
(1)把缓存实现时间设置为随机的;
(2)实时监控缓存状态,及时发现缓存异常;
100、缓存一致性问题
Cache-Aside模式:先更新数据库,再使缓存失效。
Write-Through缓存:先更新数据库,再更新缓存。
Write-Behind或Write-Back缓存:先更新缓存,然后异步或延迟更新数据库。这种策略可能会带来一定的数据不一致性风险,但可以提高写入性能。
使用分布式锁:在更新缓存时,可以使用分布式锁来保证同一时刻只有一个线程或进程能够更新缓存,避免并发更新导致的数据不一致问题。
101、Redis高可用
数据分片:将数据分布到多个Redis节点上,以减轻单个节点的负载压力。可以使用Redis Cluster或第三方工具来实现数据分片,确保数据在各个节点之间均衡分布。
哨兵模式:Redis Sentinel,可以用于监控Redis节点的状态,并在主节点故障时自动进行故障转移。通过配置多个哨兵节点,确保高可用性和故障恢复。
主从复制:使用Redis的主从复制机制,将主节点的数据实时复制到多个从节点上。通过读写分离,将读请求分发给从节点,减轻主节点的负载压力,并提高并发处理能力。
集群代理:使用第三方的代理工具如Twemproxy或Codis,将请求分发到多个Redis节点上,实现负载均衡和高并发处理。这些代理工具可以根据配置规则将请求路由到合适的节点,提高系统的并发处理能力。
102、count(1)、count(*)、count(列)的区别
Count(1)中1是一个固定值,效率要比count(*)高一些,
Count(1)和count(*)都不会过滤空值,而count(列)会过滤掉此列为空值的数据
执行效率:
列名为主键count(列)>count(1)>count(*)
列明不为主键:count(1)>ount(列)
表有多列且没有主键:count(1)>count(*)
如果表只有一个字段,则count(*)最优。
103、threadlocal父子线程同息
1、线程安全的数据存储
ThreadLocal是一种线程本地变量,父子线程之间默认是不共享的,每个线程都有自己独立的ThreadLocalMap,线程间数据是隔离的,多线程程情况下存储线程安全的数据比如用户身份、请求信息等。
2、数据共享
在一个事务中中多个线程能够访问和共享这些数据,而不需要显式地传递参数。
守护线程,给一个线程执行其他的辅助任务,常用与执行后台任务如:垃圾回收线程会在程序执行过程中自动回收不再使用的内存,定时任务。日志等。
创建方式:常用与处理一些无关紧要的任务,守护线程不能访问非守护线程的资源,因为可能会意外终止
104、更新一条没有索引的字段,会引起表锁
修改时mysql为了保证数据一致性会对受影响的行进行锁定,避免其他事务并发修改;
如果更新操作没有使用索引,数据库引擎会对整张表进行锁定;
避免表锁问题:
- 添加索引:
- 降低锁定的粒度:
3、拆分表:频繁更新表的一部分数据,可以考虑将表拆分为更小的子表,以减少锁定的范围。
调整事务隔离级别:将事务隔离级别调整为更低的级别(如读提交)可能会减少锁定的范围。
105、scp上传和下载文件
scp /path/to/local/file user@remote:/path/to/destination 上传
scp user@remote:/path/to/remote/file /path/to/destination 下载
106、gc垃圾回收
用于在程序运行回收不再使用的内存,提高内存使用的效率。
常用回收算法:分代(新生代,大部分生命周期比较短,会频繁进行垃圾回收;老年代:生命周期较长的对象,垃圾回收频率会比较低)、复制(扫描活动对象,复制到另一块空闲的内存中,释放原来的内存)、标记-清除、标记-整理
107、Volatile
1、可见性:一个线程修改某个值,加volatile后另一个线程可获得这个修改的值,否则获取不到。
2、volatile 关键字可以禁止指令重排序
当多个线程同时访问共享变量时,编译器和处理器为了优化程序的执行效率可能会对指令进行重排序,肯会出现一些线程问题。
- 分布式事务流程
保证多个独立系统或服务之间的事务操作一致性和原子性
109、遇到的问题和解决方案列举多个方案
110、分页优化
- 创建合适索引:减少数据扫描
- 预加载数据:提高数据获取效率;
- 缓存数据:分页查询的数据短时间内不会变化,可以用redis缓存分页数据
- 分片:并行请求分发到不同的分片节点查询数据;
111、oom内存泄露,mp pagehelper导致
112、final类
安全性考虑:某些类可能包含敏感信息或核心逻辑,为了防止类的继承和修改,可以将其声明为final类。
性能优化:final类的方法在编译时可以被静态绑定,这样可以提供一定的性能优化
113、守护线程会不会被回收
当所有非守护线程结束时,守护线程会自动退出,不会阻止程序的终止,被回收
114、explant的字段
id:表示查询中每个操作的唯一标识符。如果查询包含多个操作,它们将按顺序编号。
select_type:表示查询的类型。常见的类型包括 "SIMPLE"(简单查询)、"PRIMARY"(主查询)等。
table:表示所涉及的表名。
partitions:表示查询涉及的分区。
type:表示访问表的方式,通常称为"访问类型"。常见的类型有 "ALL"(全表扫描)、"INDEX"(使用索引扫描)等。
possible_keys:表示在查询过程中可能使用的索引。
key:表示实际选择使用的索引。
key_len:表示用于索引的字节数。
ref:表示与索引列进行比较的列或常量。
rows:表示估计需要扫描的行数。
filtered:表示通过表过滤的行百分比。
Extra:表示额外的信息和备注,如 "Using where"(使用了 WHERE 条件过滤)或 "Using index"(使用了覆盖索引)等。
115、服务间的调用
异步调用:调用方发送请求后立即返回,然后通过回调、消息队列或事件通知等方式接收响应。调用方可以继续执行其他操作,而不需要等待响应。
远程过程调用(RPC):RPC是分布式系统间服务通信框架,它允许一个服务像调用本地函数一样调用远程服务的函数。RPC框架通常提供了客户端和服务器端的代码生成,使得服务调用的过程更加方便和透明。
消息队列:消息队列是一种常见的异步通信机制,它允许服务通过发送和接收消息进行通信。发送方将消息发送到队列中,接收方从队列中获取消息进行处理。
RESTful API:基于HTTP协议的RESTful API是一种常见的服务间通信方式。通过定义API接口和使用HTTP方法(如GET、POST、PUT、DELETE等),服务可以通过HTTP请求和响应进行通信。
116、mysql的索引
Fulltext 全文索引、uniqueE唯一索引、normal普通索引、spatial空间索引(如获取地理位置数据)
117、一张表在同步数据到另一张表
如果同步过程中出现异常怎么解决:
异常捕获try catch
事务回滚@Transitional
数据校验:确保两表的数据结构相同
备份:先对数据进行备份
逐步同步:数据量大或者复杂的话可以进行逐步同步,而非一次性同步;