java基础10道题(第三弹)

21.关于悲观锁和乐观锁

悲观锁思路
解决线程安全的思路很多,可以从“悲观锁”的方向开始讨论。
悲观锁,也就是在修改数据的时候,采用锁定状态,排斥外部请求的修改。遇到加锁的状态,就必须等待。

虽然上述的方案的确解决了线程安全的问题,但是,别忘记,我们的场景是“高并发”。也就是说,会很多这样的修改请求,每个请求都需要等待“锁”,某些线程可能永远都没有机会抢到这个“锁”,这种请求就会死在那里。同时,这种请求会很多,瞬间增大系统的平均响应时间,结果是可用连接数被耗尽,系统陷入异常。
乐观锁思路
这个时候,我们就可以讨论一下“乐观锁”的思路了。乐观锁,是相对于“悲观锁”采用更为宽松的加锁机制,大都是采用带版本号(Version)更新,我原来在hibernate中用过。实现就是,这个数据所有请求都有资格去修改,但会获得一个该数据的版本号,只有版本号符合的才能更新成功,其他的返回抢购失败。这样的话,我们就不需要考虑队列的问题,不过,它会增大CPU的计算开销。但是,综合来说,这是一个比较好的解决方案。

有很多软件和服务都“乐观锁”功能的支持,例如Redis中的watch就是其中之一。通过这个实现,我们保证了数据的安全。

22.简单说一下sql语句是怎么优化的

我们一般在开发的时候需要注意SQL规范,比如说最基本的不要用*查询所有字段,还要就是经常用表别名,经常commit提交事务尽量让及时释放回滚点,如果使用函数的话尽量使用内部的函数,还有一个优化的地方是项目上线后,产生大量数据后,由测试人员发现某些的功能点响应比较慢,反馈给我们开发人员,我们开发人员找到这个功能点对应的sql语句,如果这个sql语句写的比较复杂,我们就得用explain去分析一下SQL语句的执行计划,看下是不是索引失效了,或者是执行到某一个子查询的语句执行比较慢,然后我们去优化这些个sql, 优化方式是什么?比如说加索引,或者创建视图.

23.什么是死锁

打个比方,假设有P1和P2两个进程,都需要A和B两个资源,现在P1持有A等待B资源,而P2持有B等待A资源,两个都等待另一个资源而不肯释放资源,就这样无限等待中,这就形成死锁,这也是死锁的一种情况。给死锁下个定义,如果一组进程中每一个进程都在等待仅由该组进程中的其他进程才能引发的事件,那么该组进程是死锁的。竞争不可抢占资源引起死锁,也就是我们说的第一种情况,而这都在等待对方占有的不可抢占的资源。

24.MyBatis执行流程

我们项目中都是结合Spring用的,我们都是把MyBatis的sqlSessionFactory交给Spring来管理的,在启动服务器的时候会通过Spring监听,加载配置文件里的所有的文件,Spring会通过反射的方式创建Mapper的实现类,我们调用Service来调用dao层的。
我们在使用springboot的时候也有结合MyBatista使用过,用的时候是他通过集成mybatis官网提供的继承tk.包下的那个mapper,会实现单表的全部增删改查

25.解释一下什么是索引?解释一下单列索引和联合索引?索引什么时候失效?,怎么添加索引?

单列索引是指在表的某一列上创建索引,联合索引是在多个列上联合创建索引。单列索引可以出现在where条件的任何位置,而联合索引需要按照一定的顺序来写。在多条件查询的时候,联合索引的效率更高,我们联合索引也最多创建两列。
我们创建索引的时候也得考虑到我们这张表的更新频率,如果表里索引比较多的话是比较影响更新速度的,为什么会影响更新速度?因为创建索引的过程其实就是构建一个二叉树,而每次更新完数据都得重新计算二叉树,所以就影响更新速度。我们表中索引我大概就了解这么多了。
索引并不是时时都会生效的,比如以下几种情况就能导致索引失效效:
1.如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)
注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引
2.like查询是以%开头,会导致索引失效
3.如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则索引失效
4.如果mysql估计使用全表扫描要比使用索引快,则不使用索引
此外,查看索引的使用情况
索引其实可以理解为数据的查询目录,建索引的目的就是为了提高对表的查询速度;没有索引时,查询时全表检索,有了索引就可以根据索引快速查找需要的数据;但是索引也不能乱建,因为索引需要维护,会导致增删改的效率降低。会使数据的维护变的复杂,影响开发的效率,索引也会占用数据库的物理空间;所以我们一般在项目的开发阶段、测试阶段、试运行阶段都很少去创建索引,因为有了索引,系统bug造成垃圾数据特别不好删除。只有在项目正式上线后才去增加索引,以提高项目运行速度。索引我们一般都创建在经常作为查询条件的字段、排序的字段和作为关联关系的字段上边。尽量避免在大文本字段、数据量比较小的字段(比如性别),增删改性能大于检索性能的字段上边;另外,有些情况,即使增加了索引,索引也不会生效,比如:索引字段使用了不等于(!=或者<>)符合,用了函数、进行了运算,使用了is null或is not null,
和不匹配的数据类型进行比较、like查询时两边都用了%等;还有一个要注意的地方是,如果在多个字段上建立联合索引,那么组合索引的第一个列被where子句引用时,索引才会起作用。因为想要使用索引增加查询效率,必然要牺牲增删改效率,为了解决这个问题,我们经常对数据库做主从复制,读写分离。同时创建两个数据库,一主一从,两个数据库数据完全一致,主的数据库用来进行写的操作,操作后数据库会自动把数据同步到从的数据库,从的数据库用来执行读的操作。这样我们建立索引时,就可以只在读的数据库创建就可以了。这样就索引即能增加查询效率,有不影响增删改效率。这样做了之后,我们还可以对他进一步优化,比如数据库引擎的优化,主数据库因为执行增删改操作,所以用事务型引擎Innodb,
读的数据库,不需要事务,就可以用效率更高的MyIASM引擎。同时根据实际情况,也可以配置一主多从或者多主多从。索引的创建常用的有2中方式:CREATE 【UNIQUE】INDEX index_name ON table_name (column_list);或者ALTER TABLE table_name ADD INDEX index_name (id,name);修改用:ALTER TABLE table_name REBUILD INDEX index_name (column_list);删除用:DROP INDEX index_name ON talbe_name
或者:ALTER TABLE table_name DROP INDEX index_name
查看用:select * from all_indexes where table_name=‘student’;
Conlum_list中多个字段用”,”号分割。

26.说一下什么事务?代码中事务是如何控制的?

在开发的时候我们同时对两条以上的sql语句进行操作,操作过程中中的如果有一条操作失败,整个事务回滚,只有全部正确才完成提交,比如说银行转账,从A账户向B账户转账,必须得两条SQL语句同时执行成功.我们在项目中直接配置到Spring里就用啦,用的注解式的事务,红色字体用于理解
Java中的事务主要有两种,JDBC事务(本地事物)和JTA(Java Transaction API)事务(分布式事物);事务有四大特性ACID原子性、一致性、隔离性和持久性。框架中,我们一般把事物交给spring来管理。spring配置事务的方式一般有两种,一个是声明式事务,一个是注解式事务。注解事务,比较简单灵活,在spring配置文件中配置一个tx:annotation-driven 饿里忒甚的注解,然后在需要的方法上加@Transactional注解就可以了。声明式事务,切点一般是扫描service层实现类,通过方法名匹配配置传播特性,决定哪些方法上加事务,哪些不需要事物。事务主要有五大隔离级别和7种传播特性;五大隔离级别由低到高:主要控制是否出现脏读,不可重复读和幻觉读;7种传播特性主要决定是新建事务,还是取当前事务;
我们在开发的时候如果不注意事务的话就会出现,脏读,不可重复读,幻读这些情况,比如说,把下面的概念挨个说一下
脏读:
指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据, 那么另外一个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的。
不可重复读:
指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
幻读:
指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户

27.死锁的发生必须具备4个条件

1.互斥条件: 其实就是进程对所分配到的资源进行排它性使用,是指在一段时间内某个资源只能由一个进程占用。如果此时还有其它进程请求资源,那么其它线程只能等待,直到占有资源的进程用完被释放掉。2.请求和保持条件: 指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。不剥夺条件: 指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。环路等待条件: 指在发生死锁时候,一定存在一个进程相当于资源的环形链,也就是进程的集合像{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源

28.Mysql优化方案?

我们一般从以下几点入手:

  1. 使用支持mysql主从复制的版本
  2. 在使用MySQL时使用索引
  3. 优化sql语句
  4. 优化MySQL服务,修改MY.INI文件,根据服务器配置缓存的大小
  5. 根据服务器配置索引的缓存
  6. 使用视图,将冗余字段放在一张表里
  7. 使用第三方技术mycat,对数据库拆分,水平拆分和垂直拆分,我们用的水平拆分
  8. 设置表内存放数据上限,同时通过mycat配置读写分离

29.mysql内部函数多了解一下

concat,trim,replace,substring,curdate() #返回当前日期,curtime() #返回当前时间,now() #返回当前日期+时间if(value,true,false) #如果value值为真,则返回true,否则,返回false
selectif (salary > 3000,‘Hight’,‘Low’) from salary;
selectid,salary, if (salary <=> NULL,‘NULL’,‘NOT NULL’) from salary;
2、ifnull(value1,value2)#如果value1不为空,则返回value1,不然返回value2
#可以用来进行空值替换
selectifnull(salary,0.00) from salary; 等 等…

30.多线程怎么解决高并发?

synchronized关键字主要解决多线程共享数据同步问题。
ThreadLocal使用场合主要解决多线程中数据因并发产生不一致问题。
ThreadLocal和Synchonized都用于解决多线程并发访问但是ThreadLocal与synchronized有本质的区别:
synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal是为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。

猜你喜欢

转载自blog.csdn.net/zhang_yuanbai/article/details/108701787