mian题目

 

1、shiro的面试 

  授权、认证、加密、会话管理

    1、Subject.login(token)进行登入,他会委托给SecurityManager

  2、SecurityManager复制真正的身份验证逻辑,它会委托给Authenticator进行身份验证

  3、Authenticator会把相应的token传入Realm中,从Realm获取身份验证信息,如果没有就返回认证失败,有的话就继续执行操作。

 

 

2、@Resource 和 @Autowried 区别

@Resource 注解是 J2EE 提供的, 而 @Autowried 是 Spring 提供的

@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了

1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
  2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
  3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
  4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配

a属性依赖了b,我们需要使用这个b,都可以使用注入,Autowired只能根据类型注入,都继承父类b,比如说c 去实现 b,d实现 b,这两个类型父类是一样的,这时候注入会提示报错

 

Resource,首先根据名称注入,然后再根据类型注入

 

4、CAS(https://blog.csdn.net/u011381576/article/details/79922538)

cas是compare and swap 的缩写,及比较交换,cas是基于锁的操作,而且是乐观锁。java中锁为乐观锁和悲观锁,悲观锁是将资源锁住,等一个之前获得锁的线程释放锁之后,下一个线程才可以访问,而乐观锁则是采取一个比较友好的态度,不加锁来处理资源,而是通过给记录加version来获取数据,性能较悲观锁有很大的提高。

cas操作有三个操作数 V(内存位置),A(旧的预期值),B(新的值),如果内存地址里面的值和A的值是一样的,那么就将内存里面的值更新成B。CAS是通过无限循环来获取数据的,若果在第一轮循环中,a线程获取地址里面的值被b线程修改了,那么a线程需要自旋,到下次循环才有可能机会执行

 

 5、java序列化和反序列化为什么要实现Serializable 接口

答:实现序列化接口可只是作为一个标记接口,告诉编译器这个类是可序列化(果我们试图序列化一个没有实现Serializable接口的对象,可能会引起一些无法预知的问题,比如对象的状态可能会丢失,或者可能会引起程序崩溃等。)

实现 Serializable 接口还有一个好处是,能够支持分布式计算、远程调用和持久化存储等应用场景。例如,如果要将一个 Java 对象通过网络传输到远程机器或持久化到磁盘上,就必须使用序列化技术。通常在分布式计算和远程调用中使用的 RMI(远程方法调用)技术和 EJB(企业 JavaBean)组件也要求实现 Serializable 接口
 
 

6、volatile 关键字

答:可以确保多线程之间的可见性

7、如何优雅的关闭线程

答:使用stop简单粗暴线程突然被中止,从而导致数据不一致的情况发生,具有不确定性,容易造成bug

  正确做法:1、两阶段中止方案,先发出中断请求,设置线程为中断状态,当线程侦测到终端状态后,再去执行中断后的清理逻辑。

 

2、标志变量来结束线程

我们可以设置一个标志变量来结束线程。这个标志变量需要使用volatile关键字来修饰,这样可以确保多线程之间的可见性。当需要结束线程时,我们只需要将这个标志变量设置为true即可。然后,我们需要在线程的run()方法中不断地检查这个标志变量的值。如果这个标志变量的值为true,我们就可以优雅的结束掉线程。

3、使用 interrupt() 方法

第二种方式,我们可以使用Thread.interrupt()方法来中断线程。这个方法会向线程发送一个中断信号,线程会收到这个信号并做出相应的响应。在线程的run()方法中,我们需要不断地检查当前线程是否被中断。如果线程被中断了,我们就可以优雅的结束掉线程。

 

 

 

 

8、spring如何解决这个循环依赖的

  答:举个例子,比如说 a 属性依赖了 b ,b类里面有依赖了a,首先spring工厂去扫描,扫描到 a 的时候去创建 a,创建a的时候会发现a里面依赖了b,这时候spring工厂会创建b,发现依赖a,会报错,spring帮我们解决的,a 放到三级工厂,容器去创建 b,从容器中获取 a,

 

 

9、线程池相关内容

     核心线程数,非核心线程数,空闲存活时间,时间单位,线程生产工厂,阻塞队列,拒绝策略

 

 

10、反射的优缺点

优点:

  1、反射机制极大的提高了程序的灵活性和扩展性,降低模块的耦合性,提高自身的适应能力。

  2、通过反射机制可以让程序创建和控制任何类的对象,无需提前硬编码目标类。

  3、使用反射机制能够在运行时构造一个类的对象、判断一个类所具有的成员变量和方法、调用一个对象的方法。

缺点:

  尽管反射机制带来了极大的灵活性及方便性,但反射也有缺点。反射机制的功能非常强大,但不能滥用。在能不使用反射完成时,尽量不要使用,原因有以下几点:
  1、性能问题。
  Java反射机制中包含了一些动态类型,所以Java虚拟机不能够对这些动态代码进行优化。因此,反射操作的效率要比正常操作效率低很多。我们应该避免在对性能要求很高  的程序或经常被执行的代码中使用反射。而且,如何使用反射决定了性能的高低。如果它作为程序中较少运行的部分,性能将不会成为一个问题。
  2、安全限制。
  使用反射通常需要程序的运行没有安全方面的限制。如果一个程序对安全性提出要求,则最好不要使用反射。
  3、程序健壮性。
  反射允许代码执行一些通常不被允许的操作,所以使用反射有可能会导致意想不到的后果。反射代码破坏了Java程序结构的抽象性,所以当程序运行的平台发生变化的时候,由于抽象的逻辑结构不能被识别,代码产生的效果与之前会产生差异。

 

 

 

 

4、spring中的ioc 和 di 的区别

核心是依赖注入,之前是我们手动创建,手动去维护,造成了一个很不方便,很难维护,ioc是spring在启动的时候把所有的类都加载到容器中,我们使用的时候只需要一些注解就可以把这些属性注入,

DI 

 

5、Spring 的Aop 

   

 

 

 

 

①、如何设置Redis键的过期时间?

②、设置完一个键的过期时间后,到了这个时间,这个键还能获取到么?假如获取不到那这个键还占据着内存吗?

③、如何设置Redis的内存大小?当内存满了之后,Redis有哪些内存淘汰策略?我们又该如何选择?

 1、redis过期的删除策略

  答:有三种删除策略(redis采用组合使用:惰性删除 和 定期删除)

    惰性删除:设置该key 过期时间后,我们不去管它,当需要该key时,我们在检查其是否过期,如果过期,我们就删掉它,反之返回该key。(db.c/expireIfNeeded 函数实现,所有键读写命令执行之前都会调用 expireIfNeeded 函数对其进行检查,如果过期,则删除该键,然后执行键不存在的操作;未过期则不作操作,继续执行原有的命令。

  优点:对 CPU友好,我们只会在使用该键时才会进行过期检查,对于很多用不到的key不用浪费时间进行过期检查。

  缺点:对内存不友好,如果一个键已经过期,但是一直没有使用,那么该键就会一直存在内存中,如果数据库中有很多这种使用不到的过期键,这些键便永远不会被删除,内存永远不会释放。从而造成内存泄漏。

    定期删除:每隔一段时间,我们就对一些key进行检查,删除里面过期的key。(由redis.c/activeExpireCycle 函数实现,函数以一定的频率运行,每次运行时,都从一定数量的数据库中取出一定数量的随机键进行检查,并删除其中的过期键

  优点:可以通过限制删除操作执行的时长和频率来减少删除操作对 CPU 的影响。另外定期删除,也能有效释放过期键占用的内存。

  缺点:难以确定删除操作执行的时长和频率。

     如果执行的太频繁,定期删除策略变得和定时删除策略一样,对CPU不友好。

     如果执行的太少,那又和惰性删除一样了,过期键占用的内存不会及时得到释放。

       定时删除:在设置某个key 的过期时间同时,我们创建一个定时器,让定时器在该过期时间到来时,立即执行对其进行删除的操作。

    优点:定时删除对内存是最友好的,能够保存内存的key一旦过期就能立即从内存中删除。

    缺点:对CPU最不友好,在过期键比较多的时候,删除过期键会占用一部分 CPU 时间,对服务器的响应时间和吞吐量造成影响

 

2、Redis过期时间的判定

   答:redis内部,每当我们设置一个键的过期时间,redis就会将改键带上过期时间存放到一个过期字典中,当我们查询一个键时,redis便首先检查该键是否存在过期字典中,如果存在,那就获取其过期时间。然后将过期时间和当前时间进行对比,比系统时间大,那就没有过期,反之过期

 

3、内存淘汰策略

 

   答:①、设置Redis最大内存

  在配置文件redis.conf 中,可以通过参数 maxmemory <bytes> 来设定最大内存

 ②、设置内存淘汰策略方法

  当现有内存大于 maxmemory 时,便会触发redis主动淘汰内存方式,通过设置 maxmemory-policy ,有如下几种淘汰方式:

  1)volatile-lru   利用LRU算法移除设置过过期时间的key (LRU:最近使用 Least Recently Used ) 。

  2)allkeys-lru   利用LRU算法移除任何key (和上一个相比,删除的key包括设置过期时间和不设置过期时间的)。通常使用该方式

  3)volatile-random 移除设置过过期时间的随机key 。

  4)allkeys-random  无差别的随机移除。

  5)volatile-ttl   移除即将过期的key(minor TTL) 

  6)noeviction 不移除任何key,只是返回一个写错误 ,默认选项,一般不会选用。

  在redis.conf 配置文件中,可以设置淘汰方式:

 

3、Redis数据同步机制

  全量复制和增量复制

 

4、CurrentHashMap 如何实现线程安全

   ConcurrentHashMap 使用的是 CAS + volatile 或 synchronized 的方式来保证线程安全的

 

 

5、java死锁如何避免?

互斥条件:一个资源每次只能被一个线程使用

请求与保持条件:一个线程在阻塞等待某个资源时,不释放已占有的资源

不剥夺条件:一个线程已获得的资源,在未使用前,不能被强行剥夺

循环等待条件:若干线程形成头尾相接的循环等待资源关系

以上是造成死锁的四个必要条件,要避免死锁,只需打破其中之一即可,但是,前三个条件是作为锁要符合的条件,我们无法打破,所以我们只能尝试打破第四个条件。可以选择让某一不重要的线程主动放弃锁来实现。

在开发过程中,注意加锁的顺序,保证每个线程按照同样的顺序加锁,注意加锁的时限,可以针对锁设置一个超时时间,注意死锁检查,这是一种预防机制,确保在发生死锁的第一时间做出反应。

 

 

 

1、分布式的共识算法,paxos,raft。zookeeper选举机制。

2、redis分布式锁实现,看门狗机制,业务逻辑没有执行完,锁过期,怎么处理,怎么检测锁过期

  分布式锁在事务中怎么释放

 

3、spring事务

锁已经释放,事务没有提及怎么办

代理方式,动态代理

 

mysql的锁有几种

间隙锁如何实现。

mysql的隔离级别

mvcc多版本并发控制,在那个级别

rr级别 可以使用mvcc解决幻读吗?

mysql的索引类型,索引结构,b+叶子节点结构。下一个叶子节点有没有指向上一个节点(双线链表),叶子节点在磁盘是不是顺序分布,叶子节点上面的数据怎么进行管理

mysql索引失效,一条索引最多会用多少个索引

慢查询怎么查看

 

单体链路如何监控请求链路

先流和熔断,进行降级。

 

查看gc日志,查看什么内容

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Java死锁如何避免?

posted @ 2023-05-08 15:24  xingmeng1  阅读(16)  评论(0编辑  收藏  举报