面试记录、问题
2022-11-25-1(三方支付)
1、i++是否是线程安全11
如果是全局变量,则 i++
不是线程安全的。因为java在处理 i++
的时候是分步操作的,编译后相当于 i= i+1
。这样的话如果第一条线程执行进来,但是还没有执行到 i++
的时候,第二条线程进来了,这个时候 i 的值还是原来的值。所以是线程不安全的。
解决方案:使用 synchronization
或者使用 AtomicInteger
.
2、线程不安全会有什么问题
会造成数据紊乱,导致业务数据错误等。例如抢票,如果线程不安全则会发生票数错误,多个人抢了票,但是剩余票数只减1,这种问题。
3、线程池创建方式及主要参数
线程池的创建主要有两种:
通过Executors创建,分别可以创建:
- FixedThreadPool(5) 固定大小的线程池,可以指定并发数量。超过则在队列中等待。
- CachedThreadPool() 可缓存线程池,若线程数超过处理所需,则会在缓存一段时间后被回收。如果线程不够则会创建新的线程。
- SingleThreadPool() 创建单个线程的线程池,保证了先进先出的顺序。
- ScheduledThreadPool() 可以执行延时任务的线程池
- SingleThreadScheduledExecutor() 创建一个单线程的可执行延时任务的线程池
- WorkStealingPool() 创建一个抢占式执行的线程池(任务执行顺序不确定)
通过 ThreadPoolExecutor 创建,也是阿里规范中推荐使用的方式,因为他可以明确线程池的规则,避免了资源耗尽等问题
主要参数:
corePoolSize:核心线程数,一直保持存活的线程数。当线程数小于核心线程数的时候,即使有空闲线程,来了新任务也会创建新的线程处理。
maxPoolSize:最大线程数。当线程数 >= 核心线程数,且队列已满,则会创建新的线程处理。当线程数 = 最大线程数的时候,则会拒绝任务并抛出异常,这个可以根据拒绝策略决定处理方式。
keepAliveTime:线程空闲时间,当线程的空闲时间达到设定值的时候会退出,直到线程数量 = 核心线程数为止。如果设置了allowCoreThreadTimeout = true,则核心线程也会超时退出。
TimeUnit:时间单位
BlockQueue:任务队列,可指定容量,当核心线程数达到最大的是后,再来新的任务则会放在这个队列中等待
ThreadFactory:线程工厂
reJectedExecutionHandler:任务拒绝处理器。
两种情况会拒绝处理任务:
- 当线程数达到最大线程数,且队列已满,怎会拒绝新任务
- 当线程池的 shutdown() 被调用的时候,会等待队列中的任务执行完毕,再shutdown。如果在调用 shutdown 和线程池真正shutdwon之间进来新任务,则会拒绝。
ThreadPoolExecutor有几个自己的内部实现来处理:
- AbortPolicy:默认值,丢弃任务,抛运行时异常
- CallerRunsPolicy:创建新线程执行任务
- DiscardPolicy:忽视,什么都不管
- DiscarOldestPolicy:从队列中踢出最先进入(最后一个执行)的任务
- 还可以实现ReJectedExecutionHandler来自定义拒绝策略。
4、如何解决sql慢查询
- 数据库创建是否适合,例如:根据表涉及的业务选择不同的存储引擎,数据量的大小考虑是否需要分库分表
- 主键是否自增类型,否则可能会引发页面分裂和记录迁移
- 是否过多的表关联查询,根据阿里规范来说是建议不要超过三张表的关联查询
- 创建索引,这里并不是说创建的索引越多越好,也要考虑到一下几种情况
- 表涉及的业务是否会频繁发生变化,毕竟数据修改是要涉及到构建索引的
- 创建的索引是否命中
- 尽量使用联合索引,要考虑最左匹配原则
- 索引失效
- 最左匹配原则为满足
- 计算、函数、类型转换都会导致索引失效
- 不等于也会导致索引失效
- is null 可以使用索引,但是is not null 就无法使用索引
- like 通配符以左模糊查询会导致索引失效
- or 关键字前后只要存咋非索引的列都会导致索引失效
- 考虑全表扫描问题,如果只是查询一条数据的话就可以加上
limit 1
使查询到就立即返回,不进行全表扫描 - 使用代码来进行处理,必要的情况下可以多次查询,之后在处理数据
5、什么情况下会发生锁表问题
锁表主要发生在 insert、update、delete中
- A程序执行了对tabbleA的insert,还没有commite时,B程序也对tableA进行了insert,这样就会发生锁表的问题
- 锁表常发生在并发的情况而不是并行,并行时,一个线程操作数据库,另一个线程是不能操作数据库的,这里是cpu的 i/o 分配原则
怎么减少锁表的发生概率:
减少insert、update、delete语句的执行到commite之间的时间,具体说就是批量执行尽量改成单个执行
6、频繁FullGC会产生什么问题,怎么引起的,怎么解决
1.