java面试题总结

中信银行

1.Integer范围问题

Integer a=100,b=100,c=200,d=200;
System.out.println(a == b);//true
System.out.println(c == d);//false

   Integer在-128~127之间会有缓存,在数字之间的地址值是一样的,超过的会new出一个新的对象。

 

2.List如何求并集

List<String> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();

//并集
list2.removeAll(list1);
list1.addAll(list2);

//交集 
list1.retainAll(list2);

//差集 
list1.removeAll(list2);

 考点List集合类collections的一些方法

 

3.三个线程同时执行,顺序输出ABC

public class TestThread1 {
    public static void main(String[] args) {
        
        // 线程A
        final Thread a = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("A");
            }
        });

        // 线程B
        final Thread b = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 执行b线程之前,加入a线程,让a线程执行
                    a.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("B");

            }
        });

        // 线程C
        final Thread c = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    // 执行c线程之前,加入b线程,让b线程执行
                    b.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("C");

            }
        });

        // 线程D
        Thread d = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    // 执行d线程之前,加入c线程,让c线程执行
                    c.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("D");
            }
        });

        // 启动四个线程
        a.start();
        b.start();
        c.start();
        d.start();
    }
}

检测线程状态的变化 join

 

4.private long val;    属性val的get set方法高并发下会不会有问题?如何处理。

public class Data {


    private int data;

    private ReadWriteLock lock = new ReentrantReadWriteLock();

    public void  set(int data){

        lock.writeLock().lock(); //取到写锁

        try {

            System.out.println(Thread.currentThread().getName()+"准备写入数据!");

            try {

                Thread.sleep(0);

            }catch (InterruptedException e) {

                e.printStackTrace(); //打印异常信息

            }

            this.data = data;

            System.out.println(Thread.currentThread().getName()+"写入"+this.data);

        }finally {

            lock.writeLock().unlock();  //释放写锁!

        }

    }

    public  void  get(){

        lock.readLock().lock();  // 取到读锁!

       try {

           System.out.println(Thread.currentThread().getName()+"准备读取数据");

           try {

               Thread.sleep(20);

           } catch (InterruptedException e) {

               e.printStackTrace(); //打印异常

           }

           System.out.println(Thread.currentThread().getName()+"读取数据!");

       }finally {

           lock.readLock().unlock();  //释放读锁!

       }

    }

}

 

 

5.Collection和Collections区别

java.util.Collection 是一个集合接口(集合类的一个顶级接口)。其直接继承接口有List与Set。

List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉,(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的,加入Set 的Object必须定义equals()方法 ,另外list支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。

Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。 
List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。 

LinkedList、ArrayList、HashSet是非线程安全的,Vector是线程安全的;

 

Collections则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。

  1. 排序(Sort) 根据元素的自然顺序 对指定列表按升序进行排序。列表中的所有元素都必须实现 Comparable 接口。此列表内的所有元素都必须是使用指定比较器可相互比较的
  2. 混排(Shuffling)
    混排算法所做的正好与 sort 相反: 它打乱在一个 List 中可能有的任何排列的踪迹。也就是说,基于随机源的输入重排该 List, 这样的排列具有相同的可能性(假设随机源是公正的)。这个算法在实现一个碰运气的游戏中是非常有用的。例如,它可被用来混排代表一副牌的 Card 对象的一个 List 。另外,在生成测试案例时,它也是十分有用的。Collections.Shuffling(list)
  3. 反转(Reverse)
    使用Reverse方法可以根据元素的自然顺序 对指定列表按降序进行排序。
    Collections.reverse(list)
  4. 替换所以的元素(Fill)
    使用指定元素替换指定列表中的所有元素。Collections.fill(li,"aaa");

……..

6.Springmvc spring boot区别,简化了哪些地方

Spring MVC是基于 Servlet 的一个 MVC 框架 主要解决 WEB 开发的问题,因为 Spring 的配置非常复杂,各种XML、 JavaConfig处理起来比较繁琐。于是为了简化开发者的使用,从而创造性地推出了Spring boot,约定优于配置,简化了spring的配置流程。

Spring 最初利用“工厂模式”(DI)和“代理模式”(AOP)解耦应用组件。大家觉得挺好用,于是按照这种模式搞了一个 MVC框架(一些用Spring 解耦的组件),用开发 web 应用( SpringMVC )。然后有发现每次开发都写很多样板代码,为了简化工作流程,于是开发出了一些“懒人整合包”(starter),这套就是 Spring Boot。

7.Springboot核心注解?

7.1.@SpringBootApplication

用于Spring主类上最最最核心的注解,自动化配置文件,表示这是一个SpringBoot项目,用于开启SpringBoot的各项能力。

相当于@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan三个注解的组合。

7.2.@EnableAutoConfiguration

允许SpringBoot自动配置注解,开启这个注解之后,SpringBoot就能根据当前类路径下的包或者类来配置Spring Bean。

例如:

当前路径下有MyBatis这个Jar包,MyBatisAutoConfiguration 注解就能根据相关参数来配置Mybatis的各个Spring Bean。

7.3.@Configuration

Spring 3.0添加的一个注解,用来代替applicationContext.xml配置文件,所有这个配置文件里面能做到的事情都可以通过这个注解所在的类来进行注册。

7.4.@SpringBootConfiguration

@Configuration注解的变体,只是用来修饰Spring Boot的配置而已。

7.5.@ComponentScan

Spring 3.1添加的一个注解,用来代替配置文件中的component-scan配置,开启组件扫描,自动扫描包路径下的@Component注解进行注册bean实例放到context(容器)中。

8.Redis如何查出1000w key  order:orderId

常规的查找key,使用的是KEYS pattern 查找所有符合给定模式pattern的key
但使用keys命令在海量数据下是有问题的

    keys指令一次性返回所有匹配的key
    键的数量过大会造成服务的卡顿, 需要等很久才会返回结果.

从海量key里查询出某一固定前缀的key 主要用到了SCAN 命令 ,该命令的格式如下:
SCAN cursor [MATCH pattern] [COUNT count]
cursor 为游标, 即从哪里开始查找, 第一次查找时,传入0.
MATCH pattern 为查找的条件
count 为返回的个数, 虽然这里可以填写返回的个数, 但是真实返回的数量是不可控的, 只能是大概率的返回符合count的参数.

SCAN 命令是一个基于游标的迭代器(cursor based iterator): SCAN 命令每次被调用之后, 都会向用户返回一个新的游标, 用户在下次迭代时需要使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程。

当 SCAN 命令的游标参数被设置为 0 时, 服务器将开始一次新的迭代, 而当服务器向用户返回值为 0 的游标时, 表示迭代已结束。一次返回的数量不可控, 只能是大概率的符合count参数
演示代码如下, 查询以order:orderId开头的key:

127.0.0.1:6379> scan 0 match order:orderId* count 10
1) "917504"
2) 1) "order:orderId:068846"
   2) "order:orderId:174741"
   3) "order:orderId:36682"
   4) "order:orderId:003555"
   5) "order:orderId:035818"
   6) "order:orderId:102763"

 

9.一个表省市区的查询语句,类似:同一张表省市县sql查询

 

SELECT 
   cy.NAME AS provice,
   cy.CODE AS proviceCode,
   ci.NAME AS city,
   ci.CODE AS cityCode,
   ct.country AS country,
   ct.cou2Code AS countryCode 
 FROM
   t_unionpay_areacode cy 
   LEFT JOIN t_unionpay_areacode ci 
     ON ci.parent_code = cy.CODE 
     AND ci.LEVEL = 2 
   LEFT JOIN 
     (SELECT 
       cou1.NAME AS city,
       cou1.CODE AS cou1Code,
       cou2.NAME AS country,
       cou2.CODE AS cou2Code 
     FROM
       t_unionpay_areacode cou1 
       LEFT JOIN t_unionpay_areacode cou2 
         ON cou2.parent_code = cou1.CODE 
         AND cou2.LEVEL = 3 
     WHERE cou1.LEVEL = 2) ct 
     ON ci.NAME = ct.city

10.数据库有上亿条数据的两个表,有关联字段如何查出表1的2000-2199两百条与表2的关联数据??

 

11.volatile的作用是什么

保持内存可见性:所有线程都能看到共享内存的最新状态。

public class TestInteger {
    private int value;
    public int get(){
        return value;
    }
    public void set(int value){
        this.value = value;
    }
}

TestInteger不是线程安全的,因为getset方法都是在没有同步的情况下进行的。如果线程1调用了set方法,那么正在调用的get的线程2可能会看到更新后的value值,也可能看不到

解决方法很简单,将value声明为volatile变量

private volatile int value;

volatile的特殊规则就是:

  • read、load、use动作必须连续出现
  • assign、store、write动作必须连续出现

所以,使用volatile变量能够保证:

  • 每次读取前必须先从主内存刷新最新的值。
  • 每次写入后必须立即同步回主内存当中。

也就是说,volatile关键字修饰的变量看到的随时是自己的最新值。线程1中对变量v的最新修改,对线程2是可见的。

12.Tomcat的结构是什么,数据量大了如何优化

来自:Tomcat内部结构、工作原理、工作模式和运行模式tomcat 体系结构详解

组成结构

Tomcat的体系结构可以由Server.xml看出

<Server>   ...   
          	
	<Service>    ...  
	<!-- A "Service" is a collection of one or more "Connectors" that share a single "Container" 
	译:service由多个connectors组成,多个service共享一个container(容器)。
	
	Note: A "Service" is not itself a "Container",so you may not define subcomponents such as 
	"Valves" at this level.Documentation at /docs/config/service.html -->       
	      
		<Connector>  ...
		<!--The connectors can use a shared executor, you can define one or more named thread pools-->
		译:多个connector共享一个执行器(指Engine),你能定义一个或多个线程进入线程池。//这个按照我的理解翻译的
		
		<!-- A "Connector" using the shared thread pool-->
		译:一个connector共享一个线程池
        </Connector>
        
        <Engine> ...  
        <!-- An Engine represents the entry point (within Catalina) that processes every request.
        译:一个Engine代表处理每个request请求的入口点(在Catalina中)
         The Engine implementation for Tomcat stand alone analyzes the HTTP headers included with the request, and passes them on to the appropriate Host (virtual host).
         Documentation at /docs/config/engine.html -->
<!-- You should set jvmRoute to support load-balancing via AJP ie :<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1"> --> 
            
	    <Host>   ... 
			               
		<Context>  ...
				                  
		</Context>
				
            </Host>
            
        </Engine>
        
    </Service>
    
</Server>

 

 

性能优化

来自:有关Tomcat提高并发量,性能优化的问题(已解决)

1.在Tomcat目录的bin/catalina.bat,打开这个文件,在前面添加一下配置

jvm在client模式,进行内存回收时,会停下所有的其它工作,待回收完毕才去执行其它任务,在这期间eclipse就卡住了。所以适当的增加jvm申请的内存大小来减少其回收的次数甚至不回收,就会是卡的现象有明显改善。  

     可以给Java虚拟机设置使用的内存,但是如果你的选择不对的话,虚拟机不会补偿。可通过命令行的方式改变虚拟机使用内存的大小。如下表所示有两个参数用来设置虚拟机使用内存的大小。

     参数      描述

    -Xms      JVM初始化堆的大小

    -Xmx      JVM堆的最大值

这两个值的大小一般根据需要进行设置。初始化堆的大小执行了虚拟机在启动时向系统申请的内存的大小。一般而言,这个参数不重要。但是有的应用程序在大负载 的情况下会急剧地占用更多的内存,此时这个参数就是显得非常重要,如果虚拟机启动时设置使用的内存比较小而在这种情况下有许多对象进行初始化,虚拟机就必 须重复地增加内存来满足使用。

    由于这种原因,我们一般把-Xms和-Xmx设为一样大,而堆的最大值受限于系统使用的物理内存。一般使用数据量较大的应用程序会使用持久对象,内存使用 有可能迅速地增长。当应用程序需要的内存超出堆的最大值时虚拟机就会提示内存溢出,并且导致应用服务崩溃。因此一般建议堆的最大值设置为可用内存的最大值 的80%。

    Tomcat默认可以使用的内存为128MB,在较大型的应用项目中,这点内存是不够的,需要调大。

    JAVA_OPTS='-Xms【初始化内存大小】

    -Xmx【可以使用的最大内存】'

    需要把这个两个参数值调大。

Windows下,在文件/bin/catalina.bat,Unix下,在文件/bin/catalina.sh的前面,增加如下设置:

  主要功能为JVM性能参数调优
 

rem 以下配置为JVM参数调优
set JAVA_OPTS=
-server     rem 以服务器模式启动,启动速度慢,但更稳定,性能更好
-Xms8192M   rem 由于本机内存为16G,这里就设置成8G(实际并未达到最大内存的80%)
-Xmx8192M   rem -Xms与-Xmx设成一样的值,避免JVM因为频繁的GC导致性能大起大落
-Xss512k 
-XX:+AggressiveOpts 
-XX:+UseBiasedLocking 
-XX:PermSize=64M    rem 内存永久保留区域 
-XX:MaxPermSize=300M     rem 内存永久保留区域 
-XX:+DisableExplicitGC  rem 禁止System.gc(),免得误调用gc方法影响性能
-XX:MaxTenuringThreshold=31 
-XX:+UseConcMarkSweepGC 
-XX:+UseParNewGC   rem 对年轻代采用多线程并行回收,这样收得快;
-XX:+CMSParallelRemarkEnabled  rem 带CMS相关的是并发回收(CMS垃圾收集器)
-XX:+UseCMSCompactAtFullCollection  rem 带CMS相关的是并发回收(CMS垃圾收集器)
-XX:LargePageSizeInBytes=128m  
-XX:+UseFastAccessorMethods 
-XX:+UseCMSInitiatingOccupancyOnly rem 带CMS相关的是并发回收(CMS垃圾收集器)
-Djava.awt.headless=true

 1).JAVA_OPTS'-Xms256m-Xmx512m'

表示初始化内存为256MB,可以使用的最大内存为512MB。

另外需要考虑的是Java提供的垃圾回收机制。虚拟机的堆大小决定了虚拟机花费在收集垃圾上的时间和频度。收集垃圾可以接受的速度与应用有关,应该通过分 析实际的垃圾收集的时间和频率来调整。如果堆的大小很大,那么完全垃圾收集就会很慢,但是频度会降低。如果你把堆的大小和内存的需要一致,完全收集就很 快,但是会更加频繁。调整堆大小的的目的是最小化垃圾收集的时间,以在特定的时间内最大化处理客户的请求。在基准测试的时候,为保证最好的性能,要把堆的 大小设大,保证垃圾收集不在整个基准测试的过程中出现。

     如果系统花费很多的时间收集垃圾,请减小堆大小。一次完全的垃圾收集应该不超过3-5秒。如果垃圾收集成为瓶颈,那么需要指定代的大小,检查垃圾收集的详 细输出,研究垃圾收集参数对性能的影响。一般说来,你应该使用物理内存的80%作为堆大小。当增加处理器时,记得增加内存,因为分配可以并行进行,而垃圾 收集不是并行的。

2.打开conf/server.xml,并更改一下内容

maxThreads 客户请求最大线程数
minSpareThreads Tomcat初始化时创建的 socket 线程数
maxSpareThreads Tomcat连接器的最大空闲 socket 线程数
enableLookups 若设为true, 则支持域名解析,可把 ip 地址解析为主机名
redirectPort 在需要基于安全通道的场合,把客户请求转发到基于SSL 的 redirectPort 端口
acceptAccount 监听端口队列最大数,满了之后客户请求会被拒绝(不能小于maxSpareThreads )
connectionTimeout 连接超时
minProcessors 服务器创建时的最小处理线程数
maxProcessors 服务器同时最大处理线程数
URIEncoding URL统一编码
 

<!-- 调优之前的配置 tomcat默认配置
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" URIEncoding="UTF-8"/>
	-->
<!-- 调优之后的配置 -->
    <Connector port="8080" protocol="HTTP/1.1"
           URIEncoding="UTF-8"  
           minSpareThreads="25" 
           maxSpareThreads="75"
           enableLookups="false" 
           disableUploadTimeout="true" 
           connectionTimeout="20000"
           acceptCount="300"   
           maxThreads="300" 
           maxProcessors="1000" 
           minProcessors="5"
           useURIValidationHack="false"
           compression="on" 
           compressionMinSize="2048"
           compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"
           redirectPort="8443"/>

保存后,启动tomcat进行压力测试。结果最后错误率还是没有改变(这里其实Tomcat的并发性能已经提高了)

3.我想可能是mysql数据的连接问题,于是编辑了数据库连接文件datasource.properties,将最大连接数与最长等待空间编辑如下

#初始连接数
db.initialSize = 20  
#定义最大连接数
db.maxActive = 200
#定义最大空间
db.maxIdle = 20
#定义最小空间
db.minIdle = 10
#定义最长等待时间
db.maxWait = 2000
db.defaultAutoCommit = true
db.minEvictableIdleTimeMillis = 3600000

最后测试结果,系统性能明显提高,并发量增大并且稳定

测试为每秒500次请求同一个接口,测试次数10次5000次请求成功,且返回数据无丢失。

并发量500无压力,并发量800无压力。

当并发量达到1000时,查看结果报告,1000次中出现三次请求失败。

4.经过以上配置,提高了系统性能,并发量接近1000次/s

 

13.Jdk线程类型

 

Hashmap  hashTable区别   currentHashMap如何保证同步,数据不重复

集合

Hashset可以存空值吗

Spring bean 是单例的吗?  默认单例  可以修改

队列queen和栈stack

Aop场景?slf4j  事务 Transactional

Feign是什么?如何使用?

Redis部署单机  集群  哨兵模式的区别

性能优化  如 查垃圾收集情况得命令

项目管理理论  敏捷开发等

 

Mysql 主键和唯一索引的区别?

主键是一种约束,唯一索引是一种索引,两者在本质上是不同的。

主键创建后一定包含一个唯一性索引,唯一性索引并不一定就是主键。

唯一性索引列允许空值,而主键列不允许为空值。

主键列在创建时,已经默认为非空值 + 唯一索引了。

主键可以被其他表引用为外键,而唯一索引不能。

一个表最多只能创建一个主键,但可以创建多个唯一索引。

主键和唯一索引都可以有多列。

主键更适合那些不容易更改的唯一标识,如自动递增列、身份证号等。

在 RBO 模式下,主键的执行计划优先级要高于唯一索引。 两者可以提高查询的速度。

 

索引的类型?

普通索引、唯一索引、全文索引

 


1.字符串截取用什么方法

2.查找一个字符串中字符的位置用什么方法

3.想要获取一个字符串中的一个单词 (这个单词有可能不在字符串中)

4.详细描述下list

5.什么是事务,怎么利用事务

6.简述下重载与重写的区别,两者父类与子类的返回值要求相同吗?

7.现场给我出了一个数据库题目,一个表,是描述奥运会中每个国家每个项目所获得的奖牌数,求每个国家所获得奖牌总数

8.简述下三大框架

9.描述你所做过的项目,谈谈其中所包含的技术

 猫迹商城:使用了springmvc框架,mybatis作为数据持久化的中间件,mysql做数据库,redis作为分布式缓存。

 一物一码营销系统:使用springboot框架,微服务思想,多模块开发,mybatis-plus工具,mysql数据库,redis做缓存。部分功能采用多线程开发,提高生产效率

 招商证券案例管理系统:非开源微服务架构,

中信银行-动卡空间-积分游戏:采用springboot框架,mybatis作为中间件,mysql数据库,redis缓存,接入eureka服务注册中心,kafka分布式消息订阅与发布系统,开发时保证业务代码的行覆盖率不低于85%,并编写单元测试。

10.怎么更改oracle字符集

11.数据库怎么优化查询

12.数据结构有哪些算法

13.什么是存储过程,简述下存储过程与函数的区别

14.什么是游标

面向对象是什么 有什么用途 封装的用途

数据库事务的四大特性是什么  以及什么是隔离性

事务的四大特性(ACID)

 

如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性:

1、原子性(Atomicity)

原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。

2、一致性(Consistency)

一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。

3、隔离性(Isolation)

隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

  即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。

4、持久性(Durability)

 

  持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

  例如我们在使用JDBC操作数据库时,在提交事务方法后,提示用户事务操作完成,当我们程序执行完成直到看到提示后,就可以认定事务以及正确提交,

即使这时候数据库出现了问题,也必须要将我们的事务完全执行完成,否则就会造成我们看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误。

事务的隔离级别(默认事务级别为可重复读)数据库事务无非就两种:读取事务(select)、修改事务(update,insert)修改时允许修改(丢失更新)
B) 修改时允许读取(脏读)
C) 读取时允许修改(不可重复读)
D) 读取时允许插入(幻读)
从上到下问题越来越不严重,但所需的性能开销却越大。

脏读
  脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。

不可重复读
  不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。

虚读(幻读)
  幻读是事务非独立执行时发生的一种现象。

低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。

MySQL数据库的四种事务隔离级别

Read Uncommitted(读取未提交内容)

 

       在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read);

Read Committed(读取提交内容)

       这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果;

Repeatable Read(可重读)

       这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。

       简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。

       InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题

Serializable(可串行化)

       这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。

         这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。例如:

 

         脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。

         不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。

         幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。

         在MySQL中,实现了这四种隔离级别,分别有可能产生问题如下所示:

        

         20151219142625513.jpg (838Ã267)

  ① Serializable (串行化):可避免脏读、不可重复读、幻读的发生。

  ② Repeatable read (可重复读):可避免脏读、不可重复读的发生。

  ③ Read committed (读已提交):可避免脏读的发生。

  ④ Read uncommitted (读未提交):最低级别,任何情况都无法保证。

 

  以上四种隔离级别最高的是Serializable级别,最低的是Read uncommitted级别,当然级别越高,执行效率就越低。像Serializable这样的级别,就是以锁表的方式(类似于Java多线程中的锁)使得其他的线程只能在锁外等待,所以平时选用何种隔离级别应该根据实际情况。在MySQL数据库中默认的隔离级别为Repeatable read (可重复读)。

  在MySQL数据库中,支持上面四种隔离级别,默认的为Repeatable read (可重复读);而在Oracle数据库中,只支持Serializable (串行化)级别和Read committed (读已提交)这两种级别,其中默认的为Read committed级别。

 

 

问了一个数据库的查询语句 怎么查出数据库中两条完全相同的数据(select * from noid a group by id,name,age having count(*)>0  这样应该可以吧... 当时没想出来)

数据库锁

列举几个复杂度nlogn的排序算法:归并排序—递归法实现

怎么用Java实现一个栈的操作 栈:后进先出集合

什么是方法重写 什么是方法重载

什么是多态 怎么实现

 

多线程,线程锁 sleep和wait区别 同步方法

这两个方法来自不同的类分别是,sleep来自Thread类,和wait来自Object类。

sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线程里调用了b的sleep方法,实际上还是a去睡觉,要让b线程睡觉要在b的代码中调用sleep。最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。

sleep不出让系统资源;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU。一般wait不会加时间限制,因为如果wait线程的运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断。

 

Spring的常用注解 列举 以及@controller 和 @service的区别

事务的注解使用

Springmvc常用的注解 列举

实习项目用到的框架,语言

1.java基本类型

2.int byte short 长度

3.字节和位的关系

4.哈希碰撞,有没有其他解决哈希碰撞的原理【没有,我就给说了一下HashMap解决哈希碰撞的方法】

5.幂等性

6.ArrayList LinkList的时间复杂度

7.数据库【刚要问,因为我们数据库数据比较少又是JPA,也没有涉及SQL优化,所以也没有怎么聊】

8.数据库ACID

9.幻读怎么回事

10.SpringMVC怎么返回实体类【当然是json】

11.SpringMVC处理流程

12.只接收GET请求,怎么办

13.讲弹性EIP项目

14.讲敏感词引擎项目

15.共享带宽项目

16.JAVA 8新特性,随便手写一个Lamda表达式

 


 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值