java面试(四)

1、Lock和Synchronized的区别

lock是一个接口,而synchronized是java的一个关键字,synchronized是内置的语言实现;

*异常是否释放锁: synchronized在发生异常时候会自动释放占有的锁,因此不会出现死锁;而lock发生异常时候,不会主动释放占有的锁,必须手动unlock来释放锁,可能引起死锁的发生。(所以最好将同步代码块用try catch包起来,finally中写入unlock,避免死锁的发生。)

*是否响应中断。lock等待锁过程中可以用interrupt来中断等待,而synchronized只能等待锁的释放,不能响应中断;

*是否知道获取锁。 Lock可以通过trylock来知道有没有获取锁,而synchronized不能;

*Lock可以提高多个线程进行读操作的效率。(可以通过readwritelock实现读写分离)

*在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。

*synchronized使用Object对象本身的wait 、notify、notifyAll调度机制,而Lock可以使用Condition进行线程之间的调度。

2、线程池的种类和线程池的组成部分

种类如下:

*CachedThreadPool(可缓存的线程池)
*.SecudleThreadPool(周期性执行任务的线程池)
*SingleThreadPool(单线程线程池)
*FixedThreadPool(定常的线程池)

组成:

*线程管理池(ThreadPool):用于创建并管理线程池,有创建,销毁,添加新任务;
*工作线程(PoolWorker):线程池中的线程在没有任务的时候处于等待状态,可以循环的执行任务;
*任务接口(Task):每个任务必须实现接口,用来提供工作线程调度任务的执行,规定了任务的入口以及执行结束的收尾工作和任务的执行状态等;
*任务队列:用于存放没有处理的任务,提供一种缓存机制。

3、事务的特性,以及四种隔离级别

事务的四大特性分别是:原子性、一致性、隔离性、持久性

*原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚
*一致性:一个事务执行之前和执行之后都必须处于一致性状态。比如,一个事务给另一个事务转10块钱,那么他俩一共只有10块钱,总量是不可能改变的。
*隔离性:多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰
*一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的

事物的四个隔离级别
第一种隔离级别:读未提交:如果一个事务开始写数据,虽然不允许其他事务也进行写操作,但是允许读,就可能出现先脏读。

第二种:读已提交:如果一个事务在进行读操作,那么允许其他事物进行读写,但如果一个事务在写操作,则禁止其他事务访问此数据,避免了脏读,但是可能出现不可重复读(事务A事先读取了数据,事务B紧接着更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。)

第三种:可重复读:可重复读取是指在一个事务内,多次读同一个数据,在这个事务还没结束时,其他事务不能访问该数据(包括了读写),这样就可以在同一个事务内两次读到的数据是一样的,因此称为是可重复读隔离级别,读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务(包括了读写),这样避免了不可重复读和脏读,但是有时可能会出现幻读。

第四种:可串行化:就是要求事务串行起来运行,不允许并发执行,是最高的隔离级别,性能也是最低的。
4、Mysql是哪种隔离级别,如何防止幻读?

可重复读。InnoDB的伪MVCC机制。

表象:快照读(非阻塞读),伪MVCC
底层:next-key(行锁+Gap锁)
a.    在RU、RC隔离级别下不存在Gap锁,所以在RU、RC隔离级别下无法解决幻读;在RR、Serializable隔离级别下都实现了Gap锁,所以解决了幻读现象。
b. 在RR隔离级别下,如果删、改、查语句的where条件走的是主键索引或者唯一索引
i. where条件全部命中,则给该记录加上记录锁。
ii. where条件不全部命中,则给该记录周围加上Gap锁。
iii. 加上记录锁或者是Gap锁都是为了防止RR隔离级别下发生幻读现象。
c. 在RR隔离级别下,如果删、改、查语句的where条件没有走索引或者是非唯一索引或非主键索引
在当前读where条件如果没有走非唯一索引或者没有走索引,则会使用Gap锁锁住当前记录的Gap,防止幻读的发生

5、mysql数据库的优化

通过8个方法优化Mysql数据库:创建索引、复合索引、索引不会包含有NULL值的列、使用短索引、排序的索引问题、like语句操作、不要在列上进行运算、不使用NOT IN和<>操作

1、创建索引
对于查询占主要的应用来说,索引显得尤为重要。很多时候性能问题很简单的就是因为我们忘了添加索引而造成的,或者说没有添加更为有效的索引导致。如果不加索引的话,那么查找任何哪怕只是一条特定的数据都会进行一次全表扫描,如果一张表的数据量很大而符合条件的结果又很少,那么不加索引会引起致命的性能下降。但是也不是什么情况都非得建索引不可,比如性别可能就只有两个值,建索引不仅没什么优势,还会影响到更新速度,这被称为过度索引。
2、复合索引
比如有一条语句是这样的:select * from users where area='beijing' and age=22;
如果我们是在area和age上分别创建单个索引的话,由于mysql查询每次只能使用一个索引,所以虽然这样已经相对不做索引时全表扫描提高了很多效率,但是如果在area、age两列上创建复合索引的话将带来更高的效率。如果我们创建了(area, age, salary)的复合索引,那么其实相当于创建了(area,age,salary)、(area,age)、(area)三个索引,这被称为最佳左前缀特性。因此我们在创建复合索引时应该将最常用作限制条件的列放在最左边,依次递减。
3、索引不会包含有NULL值的列
只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。
4、使用短索引
对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的 列,如果在前10 个或20 个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。
5、排序的索引问题
mysql查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。
6、like语句操作
一般情况下不鼓励使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可以使用索引。
7、不要在列上进行运算
select * from users where YEAR(adddate)<2007;
将在每个行上进行运算,这将导致索引失效而进行全表扫描,因此我们可以改成
select * from users where adddate<‘2007-01-01';
8、不使用NOT IN和<>操作
NOT IN和<>操作都不会使用索引将进行全表扫描。NOT IN可以NOT EXISTS代替,id<>3则可使用id>3 or id<3来代替。

发布了56 篇原创文章 · 获赞 12 · 访问量 9985

猜你喜欢

转载自blog.csdn.net/doubicheng/article/details/103644215