#JAVA常见面试题
第一章 学习好Java开发,今天不努力明天当苦力
前言
今天不努力,明天做苦力。
一、Java事务是什么?
1.事务的四大特性
1.原子性(事务包含的所有数据库操作,要么全部成功,要么全部失败回滚)
2.一致性(事务在开始前,进行中,结束后的数据库完整性没有被破坏)
3.隔离性(数据库允许多个并发事务同时对其数据进行读写,修改的能力,隔离性可以防止多个事务并发执行时,由于交叉执行而导致的数据不一致)
4.持久性(事务处理结束后,对数据的修改是永久的,即使系统故障数据也不会丢失)
2.事务的四大隔离级别
1.读未提交(所有事务都可以看到其他未提交事务的执行结果)
2.读已提交(一个事务只能看见已提交事务所做的修改,这种隔离级别可以防止脏读)默认事务隔离级别
3.可重复读(事务包含的所有数据库操作,要么全部成功,要么全部失败回滚)
4.串行化(事务包含的所有数据库操作,要么全部成功,要么全部失败回滚)
3.事务的7种传播机制
当一个具有事务控制的方法被另一个有事务控制的方法调用后,需要如何管理事务(新建事务,在事务中执行,把事务挂起,报异常)
Spring的7种事务传播机制包括:
REQUIRED:如果当前存在事务,则加入该事务,如果不存在事务,则创建一个事务。
SUPPORTS:如果当前存在事务,则加入该事务,如果不存在事务,则以非事务的方式执行。
MANDATORY:如果当前存在事务,则加入到当前事务中;如果当前没有事务,则抛出异常。
REQUIRES_NEW:总是创建一个新的事务,如果当前存在事务,则挂起当前事务。
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则挂起当前事务。
NEVER:以非事务方式执行操作,如果当前存在事务,则抛出异常。
NESTED:如果当前存在事务,则在当前事务中创建一个新的嵌套事务;如果当前没有事务,则创建一个新的事务
4.spring事务的失效场景
1.方法非public修饰(Spring无法生成动态代理,导致事务注解无效),
2.类未被spring托管事务注解不会生效
3.异常被捕获
4.自调用(在一个类的方法中调用另一个带有事务的方法)
5.事务的传播性配置错误(配置的事务 性不支持事务,事务)
6.RollbackFor属性配置错误
7.未配置事务管理器
8.数据库不支持事务
5.事务并发时存在的问题
1.脏读(指一个事务处理过程里读取另一个未提交事务中的数据)
2.不可重复读(一个事务先后读取同一条记录,而事务在两次读取之间该数据被其他事务所修改,两次读取的数据不一致)
3.幻读(一个事务按相同查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象称为幻读,两次读取的条数不一致)
二、多线程
1.怎么开启一个线程
继承Thread类,重写run()方法。
实现Runnable接口,实现run()方法。
使用Callable和Future创建线程。
使用线程池创建(使用java.util.concurrent.Executor接口)
2.线程池有哪些
1.newCachedThreadPool可缓存线程池:如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程
2.newFixedTreadPool定长线程池:可控制线程的最大并发量,超过的线程会在队列中等待
3.NewsingleTreadExecutor单线程化线程池:只会用唯一工作的线程来执行任务,保证所有执行的任务按照指定顺序执行。
4.newScheduledTreadPool定长线程池支持定时和周期性任务执行
3.线程池有哪些参数
corePoolSize核心线程数:默认不会销毁,需要allowCoreTreadTimeOut
为ture时销毁
MaximumPoolSize最大线程数:线程数量要大于核心线程数,且不能小于等于0
KeepAliveTime线程空闲时间:当一个可回收线程空闲时间
大于线程 就会被回收。
Unit线程空闲时间单位:
TreadFactory线程的创建工厂
Handler线程拒绝策略:
WorkQueue工作队列:存放待执行的任务队列,当提交的任务数超过核心线程数后,再提交的任务就存放在工作队列,任务调度时再从队列中取出任务,它仅仅用来存放被execute()方法提交的Runnable任务。工作队列实现的是blockingQueue接口
3.线程池线程4种拒绝策略
AbortPolicy:丢弃任务并抛出RejectedExcutionException异常
DiscardPolicy:丢弃任务但不抛出异常 mn
DiscardoldestPolicy:丢弃最前面的队列任务,然后重新提交被拒绝的任务
CallerRunsPolicy:由调用线程处理该任务
4.线程池线程工作队列有五种
ArrayBlockingQueue 数组阻塞队列:数组结构,初始化时传入大小,有界,FIFO(先入先出),使用一个重入锁,默认使用非公平锁,
LinkedBlockingQueue 链表型阻塞队列:链表结构,默认初始化大小为Integer.MAX_VALUE, 有界(无界),FIFO(先入先出),使用两个重入锁分别控制元素的入队和出队,用Condition进行线程间的唤醒和等待
SynchronousQueue 同步队列:容量为0,添加任务必须等待取出任务,这个队列相当于通道,不存储元素。
PriorityBlockingQueue 优先阻塞队列:无界,默认采用元素的自然顺序升序排列
DelayQueue 延时队列:无界,元素有过期时间,过期的元素才能被取出
5.多线程异步执行,等待执行全部执行完成后,返回全部结果怎么实现
异步执行多个任务,获取每个任务的结果。根据任务结果判断是否继续后面的操作
方法1. 使用Future ,示例:按循序执行,等获取到指定任务的结果后再继续执行
// 调用get时会阻塞线程,获取到结果后才向下进行,因此在使用时,一般都会用 get(long timeout, TimeUnit unit) 设置超时时间
代码如下(示例):
ExecutorService executorService = Executors.newFixedThreadPool(3);
Future<String> submit = executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(3000);
// 需要处理异常
// if(Math.random()!=0.3){
// throw new RuntimeException("手动异常");
// }
return "我是任务1结果";
}
});
Future<String> submit2 = executorService.submit(new Callable<String>() {
@Override
public String call(