千里之行,始于足下

事务是什么?

作为单个逻辑工作单元执行的一系列操作,这一系列操作要么全部执行成功,要么全部执行失败。

事务的四大特性(ACID)?

原子性(Atomicity):事务是一个不可分割的逻辑工作单元,事务中的一系列操作要么全部成功,要么全部失败。

一致性(Consistency):事务必须使数据库从一个一致性状态变换到另一个一致性状态。我们假设用户A和用户B两个人的账户加起来有5000块钱,那么不管A和B之间如何转账,事务结束后两个人的账户加起来还得是5000块钱,这就是一致性状态。

隔离性(Isolation):多个用户并发访问数据库时,数据库为每一个用户开启一个事务,多个并发事务之间相互隔离,不会相互干扰。

持久性(Durability):一个事务一旦被提交了,那么对数据库中的数据的改变是永久性的,即使数据库系统出现故障也不会丢失提交事务的操作。

事务没有隔离会出现哪些问题?

脏读:事务A读取到事务B未提交的数据

不可重复读:事务A读取同一个数据两次,这两次中间事务B修改了这个数据并提交,导致事务A读取的数据不一致

幻读(虚读):事务A批量更新一批数据中的某一字段期间,事务B在这批数据中插入或者删除一条数据,事务A提交的时候,发现了一条自己未修改的数据

更新丢失:两个事务同时更新一个数据,势必导致一个更新会丢失

事务的隔离级别?

读未提交(read-uncommitted):能读到其它事务未提交的数据,不能防止脏读、不可重复读、幻读问题

读已提交(read-committed):能读到其它事务已提交的数据,能防止脏读,不能防止不可重复读、幻读。(Oracle默认的隔离级别)

可重复读(repeatable-read):能重复读取同一个数据,读的时候加一把锁,防止其它事务对这一数据进行更新操作,能防止脏读、不可重复读,不能防止幻读。(MySQL默认的隔离级别)

串行化(serializable):最高的隔离级别,并发事务串行化执行,不会相互干扰,能防止脏读、不可重复读、幻读问题。

Spring 事务的传播机制?

propagation_required(spring 默认):支持当前事务,如果当前没有事务,则新建一个事务。比如:方法A内部调用方法B,如果A开启了事务,则B会运行在A的事务内,如果A没开启事务,则B会为自己分配一个事务。

propagation_requires_new:新建事务,如果外层存在事务,则将外层事务挂起,等当前事务执行完毕再执行外层事务。外层事务回滚不影响当前事务,当前事务回滚,如果外层捕获了异常就不影响外层事务回滚,如果没有捕获异常会进行回滚。注意事项:如果在同一个类中,方法A开启了默认事务,方法B新建了事务,由于动态代理的原因,在invoke方法中无法在此代理方法B,所以直接当作普通方法调用,导致事务失效。

propagation_supports:支持当前事务,如果当前没事务,则以非事务的方式运行。比如方法A内部调用方法B,如果A开启了事务,则B加入到此事务中,如果A没事务,B也不开启事务

propagation_mandatory:支持当前事务,如果当前没事务,则抛出异常。

propagation_not_supported:如果当前存在事务,则将事务挂起,自己以非事务的方式运行。

propagation_never:非事务方式运行,如果当前存在事务,则抛出异常。

propagation_nested:如果当前没事务,则进行与propagation_required类似的操作,如果当前存在事务,则嵌套事务内执行,成为外部事务的一个子事务,子事务回滚会回滚到一个保存点,外部事务如果回滚,子事务也会回滚,外部事务提交,子事务一起提交,子事务异常回滚,外部事务正常可以提交。仅仅支持DataSourceTransactionManager作为事务管理器。

什么是死锁?

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,无法继续执行。

死锁产生的四个必要条件?

互斥条件:进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。

请求与保持条件:指进程已经保持至少一个资源,但又请求新的资源,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。

不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

循环等待条件:指在发生死锁时,必然存在一个进程—资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。

解决死锁的方法?

1、所有的锁都按照特定的顺序获取
2、线程获取锁超时后,主动释放之前获取的所有锁
3、一次性锁住所有资源

Cookie 和 Session 的区别?

cookie 数据保存在客户端,session 数据保存在服务端

session 比 cookie 更具有安全性,可以将重要信息放在session中,无关紧要的信息放在cookie中

单个 cookie 大小不能超过4k,session 没限制,内存大小跟服务器大小有关,session 过多会影响服务器性能

session 能存储任意的 java 对象,cookie 只能存储 String 类型的对象

jre 与 jdk 的区别?

jre 包含了jvm和基础类库等,支撑Java程序的运行;jdk 包含了jre,还包含了编译器javac,开发工具和更多的类库等,支撑Java程序员开发Java程序

Java 中有哪些数据类型?

基本数据类型:byte、short、int、long、float、double、char、boolean

引用数据类型:类、接口、数组

== 和 equals 有什么区别?

==:对于基本数据类型,比较的是值,对于引用数据类型,比较的是引用地址

equals:String 类中重写了Object类的equals方法,先比较引用地址,如果一样,直接返回true;如果不一样,再比较值是否相同

String、StringBuffer、StringBuilder 有什么区别?

String:字符串常量,每次改变内容都会产生新的对象,只适合少量字符串操作的情况

StringBuffer:字符串变量,线程安全,性能低,适合多线程下使用

StringBuilder :字符串变量,线程不安全,性能高,适合单线程下使用

HashMap 和 HashTable 有什么区别?

1、HashMap 继承自AbstractMap类;HashTable 继承自Dictionary类

2、HashMap 线程不安全;HashTable 线程安全

3、HashMap 无contains方法;HashTable 有contains方法

4、HashMap 允许key和value为null值;HashTable 不允许key和value为null值

5、HashMap 通过hashCode值的高16位亦或低16位,得到新hash值;HashTable 直接用的hashCode值作为hash值

6、HashMap 计算索引位用的是数组长度减一按位与hash值;HashTable 计算索引位直接是hash值对数组长度取模运算

7、HashMap 扩容2倍;HashTable 扩容2倍加1

8、HashMap 底层结构是数组+链表+红黑树;HashTable 底层结构是数组+链表

Spring 是什么?

Spring 是一个轻量级的IoC和AOP的容器框架,是为Java应用程序提供基础性服务的一套框架,目的是简化企业应用程序的开发。

说一说对Spring中Ioc的理解?

Ioc就是控制反转,指的是将创建对象的控制权交给Spring框架,由Spring框架根据配置文件去创建实例和管理各个实例之间的依赖关系。

数据库锁分类

按锁粒度分类

行锁:锁一行的数据

  • 特点:粒度小,锁冲突概率低,并发度高;锁开销大,加锁慢,容易出现死锁

页锁:锁住一页的数据

  • 特点:粒度介于行锁和表锁之间,会出现死锁,并发度一般

表锁:锁住整张表的数据

  • 特点:粒度大,锁冲突概率高,并发度低;锁开销小,加锁快,不会出现死锁

从程序员角度划分

乐观锁:每次去拿数据的时候都认为别人不会修改,不会上锁,更新的时候再去判断数据有没有被修改

悲观锁:每次去拿数据的时候都认为别人会修改,会上锁,其它事务拿这个数据时会被阻塞,直到锁被释放

从数据库角度划分

共享锁(S):锁定的数据可以被其它事务读,但是不能被修改

排它锁(X):锁定的数据不允许其它事务读和写

意向锁:告知其它事务,表中是否有数据行被锁定。(当要获取表的排它锁的时候,需要先判断表中是否有数据上了行锁)

间隙锁(Next-Key):保证某个间隙内的数据在锁定情况下不会发生任何变化。用范围条件检索数据的时候,InnoDB会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁。

Redis 内存淘汰机制有哪些

redis在内存空间不足的时候,为了保证命中率,就会选择一定的数据淘汰策略;我们可以在 redis.config 中设置最大的内存参数,默认是关闭的。redis5.0为我们提供了八个不同的内存置换策略,以前是6种。

  • volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰
  • volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰
  • volatile-random:从已设置过期时间的数据集中任意选择数据淘汰
  • volatile-lfu:从已设置过期时间的数据集挑选使用频率最低的数据淘汰
  • allkeys-lru:从数据集中挑选最近最少使用的数据淘汰
  • allkeys-lfu:从数据集中挑选使用频率最低的数据淘汰
  • allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
  • no-enviction(驱逐):禁止驱逐数据,这也是默认策略。意思是当内存不足以容纳新入数据时,新写入操作就会报错,请求可以继续进行,线上任务也不能持续进行,采用no-enviction策略可以保证数据不被丢失

这八种大体上可以分为4中,lru、lfu、random、ttl。

Redis 过期策略有哪些

  • 惰性删除:查询某个 key 的时候,redis 会先检查一下,查看这个key是否设置了过期时间,如果设置了过期时间,那判断是否过期,过期了就删除
  • 定期删除:redis 默认是每隔 100 ms 就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期了就删除
  • 主动删除:如果定期删除漏了很多过期的key,也没有频繁的查询key,过期的key堆积多了导致内存不够,这时候会走内存淘汰机制

手写一下LRU代码实现

public class LRUCache<Object> {
    /**
     * 默认缓存大小
     */
    private int CAPACITY = 0;

    private LinkedList<Object> list;

    public LRUCache(int capacity){
        this.CAPACITY = capacity;
        list = new LinkedList<Object>();
    }

    public synchronized void put(Object object){
        if (list != null && list.contains(object)){
            list.remove(object);
        }
        removeLeastVisitElement();
        list.addFirst(object);
    }

    /**
     * 移除最近访问次数最少的元素
     */
    private synchronized void removeLeastVisitElement() {
        int size = size();
        //注意,这儿必须得是CAPACITY - 1否则所获的size比原来大1
        if(size > (CAPACITY - 1) ) {
            Object object = list.removeLast();
            System.out.println("本次被踢掉的元素是:" + object.toString());
        }
    }

    public int size() {
        if(list == null) {
            return 0;
        }
        return list.size();
    }

    public synchronized Object get(int index) {
        return list.get(index);
    }

    public synchronized void clear() {
        list.clear();
    }

    @Override
    public String toString() {
        return list.toString();
    }
}

// 测试
LRUCache<String> lruCache = new LRUCache<>(3);
lruCache.put("a");
System.out.println(lruCache.toString());
lruCache.put("b");
System.out.println(lruCache.toString());
lruCache.put("c");
System.out.println(lruCache.toString());
lruCache.put("d");
System.out.println(lruCache.toString());
lruCache.put("e");
System.out.println(lruCache.toString());

测试结果:

[a]
[b, a]
[c, b, a]
本次被踢掉的元素是:a
[d, c, b]
本次被踢掉的元素是:b
[e, d, c]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值