JAVA面试集锦

目录

一、Redis持久化后,数据会一直不丢失吗

二、Spring中定义bean的方式

三、如何理解Spring的自动配置 

四、@Autowrired和@Resource注解的区别

五、事务失效的几种情况

六、多线程

1、Java中有几种方式创建线程

2、线程的几种状态

3、如何设置线程数

七、Sychronized的锁的升级过程

八、什么是InnerDb中的页

九、MYSQL索引失效的几种场景


一、Redis持久化后,数据会一直不丢失吗


1、RDB 跟持久化策略相关。 save 60 1,60s内执行一次写命令,持久化一次。save 300 10,300s内执行10次写命令,才持久化,假设只执行了5次,宕机了,数据就没了
2、AOF
通过持久化命令保证数据持久化

appendfsunc always  每次执行命令,会将写命令存到内存aof buffer,就将写命令进行持久化
appendfsunc everysec 默认策略,每次执行命令,会将写命令存到内存aof buffer,每隔1s持久化
appendfsunc no  每次执行命令,会将写命令存到内存aof buffer,redis不主动持久化,交由操作系统

默认情况下,AOF也会丢失1s的数据

3、混合(Redis4.0后)

二、Spring中定义bean的方式


1、@Bean
2、@Component  
3、@Controller  @RestController @Service @Repository
4、ControllerAdvice、@RestControllerAdvice
5、@Configuration 配置bean
可以再去定义一些bean
6、@Import(ProductService.class) 
7、BeanDifinition  实现ImportBeanDefinitionRegister  声明一个类
8、<bean/>标签

三、如何理解Spring的自动配置 


@EnableAutoConfiguration 自动配置注解生效
@SpringBootConfiguration
@ComponentScan
以上3个注解等于1个注解 @SpringBootApplication

四、@Autowrired和@Resource注解的区别

private ProductService(类型)  productService(名字)

@Autowired  先根据类型 ,找到多个在根据名字。是Spring提供的

@Resource 先根据名字找,在根据类型找,找到多个会报错。
如果自定义了名字,就只根据名字找,如@Resource(name="xxxService")

@Inject 也是现根据类型,再跟进名字,它是JDK层面提供的

Online DDL 相当于和其他事务并行,只不过会在表空闲时才会去执行,不会去阻塞其它的语句

五、事务失效的几种情况

@Transaction  代理对象才有效
开启sring事务
事务管理器新建一个数据库连接conn
conn.autocommit=false
普通对象执行test()方法 抛异常  conn.rollback(); 正常 coon.commit


事务失效的情况
1、方法内自调用,spring事务是基础AOP的,只有使用代理对象调用某个方法时才能生效,
而在一个方法中调用使用this.xxx()调用时,this不是代理对象,会导致事务失效。
解决方法:把调用方法拆分到另一个bean里、自己注入自己、
2、方法是private的   Spring事务基于CGLIB来进行AOP,而CGLIB会基于父子类来失效,子类是
代理类,父类是被代理类,如果父类中的某个方法是private的,那么子类就没办法重写它,也就没有办法额外增加Spring事务的逻辑
3、方法是Final的,原因子类不能重新父类的final方法
4、单独的线程调用,不懂----
5、没有加注解,使用SpriongBoot没有这个问题,Spring 下会出现此种情况。原因,mybatis或者JdbcTemplate会从ThreadLocal中获取数据库连接,但是
ThreadLocal中存的是MAp,Map的key为DateSource对象,value为连接对象,如果没有加注解,会导致Map中DateSource对象与Mybatis或JdbaTemplate的不相等,
从而拿不到连接,导致自己去创建数据库连接了,此时的autoCommit为true。
6、异常被吃掉,默认情况下会捕获RunTineException和Error
7、类没有被Spring管理
8、数据库不支持事务

六、多线程

1、Java中有几种方式创建线程

  1. 继承Thread类
  2. 实现Runnable接口,实现run()方法
  3. 实现Callable接口,可以拿到任务结果,结合FutureTask
    public class XxxService implement Callable<String> {
    
    
    public static void main(String[] args){
    
      FutureTask<String> futureTask = new FutureTask<>(new XXXThread);
    
      Thread thread = new Thread(futureTask );
    
      thread.start();
    
      String result = futureTask.get();
    }
    
    public String call(){
       return "hahah";
    }
  4.  利用线程池创建线程:
  • 使用newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
  • 使用newFixedThreadPool,创建一个指定工作线程数量的线程池。
  • 使用newSingleThreadExecutor,创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO,优先级)执行。如果这个线程异常结束,会有另一个取代它,保证顺序执行。单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。
  • 使用newScheduledThreadPool,创建一个定长的线程池,而且支持定时的以及周期性的任务执行,支持定时及周期性任务执行。

        为什么不建议使用 Executors来创建线程池?

        因为 底层是LinkedBlockedeue无界阻塞队列,执行的任务越多,就会不断地添加到队列中,占用的内存就越多,最终会导致内存耗尽,导致OOM。建议直接使用ThreadPoolExector来定义线程池。

2、线程的几种状态

  • Running 表示线程正常运行
  • ShutDown 表示线程处于正在关闭状态,不在接受新任务,但是会继续把队列中的任务处理完
  • ShutDownNow  表示线程处于正在停止状态,不在接受新任务,也不会处理队列中的任务,并且正在运行的任务也会被中断。
  • Diying 线程池中没有线程运行,就会进入Diying状态,并且会调用Terminated()
  • TERMINATED Terminated()方法执行完,就进入Terminated()。

3、如何设置线程数


CPU密集时 设置CPU核心数+1;线程执行时,会一直利用CPU,对于这种情况,尽可能减少线程上线文的切换

比如:电脑只有1个CPU,两个线程同时执行找素数的任务,总执行时间为  执行时间*2+线程上下文切换

对于Cpu密集型任务,线程数最好等于CPU核心数,可以通过以下API拿到电脑核心数:
RunTime.getRuntime().availaableProcessors();


4、IO执行时间越长,同时阻塞在IO上的线程数越多,就可以设置更多线程
线程数=CPU核心数*(1+线程等待时间/线程运行总时间)  通常会设置2*线程数

七、Sychronized的锁的升级过程

1、偏向锁 

指的是线程获取到了锁之后,在锁的头部会记录一个线程id,下次线程在来获取锁可以直接获取到,也就是锁重入

2、轻量级锁

是由偏向锁升级而来,指的是当一个线程获取到了锁,另一个线程来竞争时,会升级为轻量级锁,底层通过自旋来实现,不会阻塞线程。

3、重量级锁

经过多次自旋,依旧未获取到锁,会升级为重量级锁,此时会堵塞线程

自旋锁:所得 就是线程去获取锁的过程中,不会堵塞线程,也就无所谓锁的唤醒,堵塞和唤醒是操作系统执行的,所以也就不耗费资源。自旋是 通过CAS来获取预期的一个标记,获取到了则获取锁成功,这个过程线程一直是运行的,相对而言没有使用太多操作系统资源,是轻量的。

八、什么是InnerDb中的页

查询时,从磁盘读取数据,放进内存

一页是16KB,一页分为3部分:页头、页目录、存储数据区域

 select * from table where a =  3;执行方式,先遍历页目录,在去遍历具体的那一组,通过页目录进一步提高查询效率。

如果插入不是用自增id,会导致以前已经存好的数据,发生改变。比如第一页数据已满(1 2 3 6),这时新增一个数字4,排序应该在第一页,会导致6移动到第二页。

怎么判断数据在第几页?通过索引页判断、找到数据页

九、MYSQL索引失效的几种场景

  1. 不符合最左匹配原则  提供索引列的最左字段
  2. LIke百分号左边失效
  3. 对索引列进行计算、或使用函数
  4. 索引列进行了类型转换。 
    比如一个 varchar类型 给了数字。 a=1,索引会失效,mysql会将字段转换成数字
    但是如果 a是int类型,a= '1',不会失效,mysql执行时只需要将值转换数字
  5. order by 回表
  6. 不等于 <>
  7. or
  8. 范围查询数量过大
  9. select * 导致索引失效

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值