zoukankan      html  css  js  c++  java
  • java面试

    1.java多线程

    1.1 java多线程通信?

    多线程并发编程时,难免会遇到线程间的通信问题。线程通信方式的思想大体上来说可以分为两种:共享和传递

    共享的实现方式可以是共享变量、共享文件、数据库、网络等。传递的实现方式可以是消息队列、生产者-消费者模型等。

    (1)共享变量:

                     使用volatile 关键字定义共享变量  private static volatile Boolean odd = true。

                      多个线程同时监听一个变量,当这个变量发生变化的时候 ,线程能够感知并执行相应的业务。

                      volatile 保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新。

    (2)使用Object类的wait() 和 notify() 方法:

                     wait和 notify必须配合synchronized使用,wait方法释放锁,notify方法不释放锁。

    (3)基本LockSupport实现线程间的阻塞和唤醒:

                     LockSupport.park();                  阻塞

                     LockSupport.unpark(threadB); 唤醒

    1.2 java多线程实现方式?

    (1)继承Thread类创建线程。

    (2)实现Runnable接口创建线程。    多,多实现单继承。

    (3)java的Executors线程池。减少对象创建, 提供定时执行、定期执行、单线程、并发数控制等功能。

    1.3 java什么是线程池?

    创建线程需要花费资源和时间,如果等任务来创建线程那么响应时间就变长。

    在程序启动时创建线程来响应处理就是线程池。

    1.4 java多线程start()与run()方法区别?

    start():Thread类start()来启动一个线程,这时此线程是处于就绪状态, 并没有运行。 然后通过此Thread类调用方法run()来完成其运行。

                 run()称为线程体,它包含了要执行的这个线程的内容。

    run(): run()方法当作普通方法的方式调用,程序还是要顺序执行。没有达到多线程目的。

    1.5 java多线程中wait()与sleep()区别?

    (1)wait是Object方法,sleep是线程方法。

    (2)wait会释放锁,sleep不释放锁。

    (3)wait需要依赖synchronized关键字,sleep方法不依赖于同步器synchronized。

    1.6 synchronized与static synchronized区别?

    synchronized锁的是对象

    static synchronized锁的是类

    2.java基础

    2.1 java多态?

    不同类的对象对同一消息作出不同的响应就叫做多态。

    多态存在的三个条件:

                            (1)有继承关系。

                            (2)子类重写父类方法。

                            (3)父类引用指向子类对象,父类调用方法会调用子类重写后方法。FU fu=new ZI();

    2.2 java中final关键字?

    (1)final成员变量表示常量,只能被赋值一次,赋值后值不再改变。

    (2)final方法不能被子类的方法重写,但可以被继承。

    (3)final类不能被继承,没有子类,final类中的方法默认是final的。

     (4)final不能用于修饰构造方法。

    2.3 java中static关键字?

    (1)静态变量。类加载只为分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问。

    (2)静态方法。静态方法可以直接通过类名调用。静态方法不能访问非静态方法。

    (3)static代码块。类加载的时候就会依次执行一次静态代码块。

    2.4 接口保证幂等性是基本的要求,那么幂等性你们是怎么做的?

    接口的幂等性实际上就是接口可重复调用,在调用方多次调用的情况下,接口最终得到的结果是一致的。有些接口可以天然的实现幂等性,比如查询接口,对于查询来说,你查询一次和两次,对于系统来说,没有任何影响,查出的结果也是一样。

    除了查询功能具有天然的幂等性之外,增加、更新、删除都要保证幂等性。那么如何来保证幂等性呢?

    2.4.1 全局唯一ID

    如果使用全局唯一ID,就是根据业务的操作和内容生成一个全局ID,在执行操作前先根据这个全局唯一ID是否存在,来判断这个操作是否已经执行。如果不存在则把全局ID,存储到存储系统中,比如数据库、redis等。如果存在则表示该方法已经执行。

    从工程的角度来说,使用全局ID做幂等可以作为一个业务的基础的微服务存在,在很多的微服务中都会用到这样的服务,在每个微服务中都完成这样的功能,会存在工作量重复。另外打造一个高可靠的幂等服务还需要考虑很多问题,比如一台机器虽然把全局ID先写入了存储,但是在写入之后挂了,这就需要引入全局ID的超时机制。

    使用全局唯一ID是一个通用方案,可以支持插入、更新、删除业务操作。但是这个方案看起来很美但是实现起来比较麻烦,下面的方案适用于特定的场景,但是实现起来比较简单。

    2.4.2 防重复提交策略

    上述的保证幂等方案是分成两步的,第②步依赖第①步的查询结果,无法保证原子性的。在高并发下就会出现下面的情况:第二次请求在第一次请求第②步订单状态还没有修改为‘已支付状态’的情况下到来。

    既然得出了这个结论,余下的问题也就变得简单:把查询和变更状态操作加锁,将并行操作改为串行操作。

    2.4.3 防重表

    这种方法适用于在业务中有唯一标的插入场景中,比如在以上的支付场景中,如果一个订单只会支付一次,所以订单ID可以作为唯一标识。这时,我们就可以建一张去重表,并且把唯一标识作为唯一索引,
    在我们实现时,把创建支付单据和写入去去重表,放在一个事务中,如果重复创建,数据库会抛出唯一约束异常,操作就会回滚。

    2.4.4多版本控制

    这种方法适合在更新的场景中,比如我们要更新商品的名字,这时我们就可以在更新的接口中增加一个版本号,来做幂等
    
    boolean updateGoodsName(int id,String newName,int version);

    2.4.5状态机控制

    这种方法适合在有状态机流转的情况下,比如就会订单的创建和付款,订单的付款肯定是在之前,这时我们可以通过在设计状态字段时,使用int类型,并且通过值类型的大小来做幂等,比如订单的创建为0,付款成功为100。付款失败为99
    
    在做状态机更新时,我们就这可以这样控制
    
    update `order` set status=#{status} where id=#{id} and status<#{status}

    2.5 @Transactional来控制事务,那么能不能说出一些事务不生效的场景?

     2.5.1数据库引擎不支持事务

     2.5.2没有被spring管理

    我们会把事务注解加到service层,如果没有@Service注解,这个类就不会被加载成一个Bean,那这个类就不会被spring管理,事务自然就失效了。。

     2.5.3 就是在@Transactional方法内部捕获了异常,没有在catch代码块里面重新抛出异常,事务也不会回滚。

    所以在阿里巴巴的Java开发者手册里面有明确规定,在 @Transactional的方法里面捕获了异常,必须要手动回滚,
    代码如下:
    
     @Override
        @Transactional
        public void insertOne() {
            try {
                UserEntity userEntity = new UserEntity();
                userEntity.setUsername("Michael_C_2019");
                //插入到数据库
                userMapper.insertSelective(userEntity);
                //手动抛出异常
                throw new IndexOutOfBoundsException();
            } catch (IndexOutOfBoundsException e) {
                e.printStackTrace();
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            }

     2.5.4 同一个类中方法调用,导致@Transactional失效

    开发中避免不了会对同一个类里面的方法调用,比如有一个类Test,它的一个方法A,A再调用本类的方法B(不论方法B是用public还是private修饰),但方法A没有声明注解事务,而B方法有。则外部调用方法A之后,方法B的事务是不会起作用的。这也是经常犯错误的一个地方。
    
    那为啥会出现这种情况?其实还是由于使用Spring AOP代理造成的,因为只有当事务方法被当前类以外的代码调用时,才会由Spring生成的代理对象来管理。
    
     //@Transactional
        @GetMapping("/test")
        private Integer A() throws Exception {
            CityInfoDict cityInfoDict = new CityInfoDict();
            cityInfoDict.setCityName("2");
            /**
             * B 插入字段为 3的数据
             */
            this.insertB();
            /**
             * A 插入字段为 2的数据
             */
            int insert = cityInfoDictMapper.insert(cityInfoDict);
     
            return insert;
        }
     
        @Transactional()
        public Integer insertB() throws Exception {
            CityInfoDict cityInfoDict = new CityInfoDict();
            cityInfoDict.setCityName("3");
            cityInfoDict.setParentCityId(3);
     
            return cityInfoDictMapper.insert(cityInfoDict);
        }

     2.5.5 @Transactional修饰的方法为非public方法

    根据spring官网,@Transactional只能用于public的方法上,否则事务不会生效,如果非要用在非public方法上,可以开启AspectJ代理模式。AspectJ使用加载时织入的方式,支持所有的pointcut,因此可以支持内部方法的事务设置。

     2.6 String, StringBulider, StringBuffer区别?

    String适用于少量字符串操作。

    StringBuilder单线程大量操作,不是线程安全的。

    StringBuffer多线程大量操作,线程安全。

    String常量,StringBuilder和StringBuffer字符串变量。

    运行速度StringBuilder>StringBuffer>String。

     2.7 SpringMVC和Struct2区别?

    SpringMVC入口是servlet, Struct2入口是filter

    SpringMVC是基于方法, Struct2基于类

    2.8 字符流和字节流的区别?

    字符流用于处理文本,

    字节流处理任何数据类型,计算器中数据以字节存储

    2.9 Exception和error区别?

    exception需要程序捕捉或者处理掉的异常

    error系统级的错误

    2.10 JAVA构造函数?

    方法名与类名相同,没有返回值,

    作用: 对象一建立就自动调用构造函数,

    2.11 cookie和session的区别?

    cookie数据存储在浏览器上,session在服务器上

    cookie不安全,session安全

    2.12 get与post请求区别?

    get: 请求参数会显示在浏览器地址上,不安全, 长度有限制请求参数1k,get没有请求体

    post: 请求参数不会显示在浏览器地址,相对安全,参数无限制

    2.13 JAVA动态代理?

    给方法添加预处理或者添加后续操作,不干预正常业务,SpringAop原理就是基于动态代理实现的.

    实现方式:

    1.JDK        实现invacationHandler接口 invoke()方法

    2.CGLIB    实现methodInterceptor接口 intercept()方法

    区别:  JDK反射机制提供的代理.

              CGLIB是利用asm开源包修改代理对象的字节码来处理.

    3.数据库

    3.1 mysql explain 查看sql语句执行计划

    3.2 mysql查看进程 show processList

    3.3 mysql触发器

    一张表发生某件事件(插入,删除,更新), 就会自动触发预先编写好的sql语句。create trigger

    增加程序复杂度使后期维护变得困难,尽量在代码中处理。

    3.4 数据库的隔离级别

    3.4.1读取未提交的。

    读未提交,顾名思义,就是可以读到未提交的内容。

    因此,在这种隔离级别下,查询是不会加锁的,也由于查询的不加锁,所以这种隔离级别的一致性是最差的,可能会产生“脏读”、“不可重复读”、“幻读”。

    如无特殊情况,基本是不会使用这种隔离级别的

    3.4.2.读取已提交的。

    读提交,顾名思义,就是只能读到已经提交了的内容。

    这是各种系统中最常用的一种隔离级别,也是SQL Server和Oracle的默认隔离级别。

    3.可重复读。

    同一事务下,两次相同查询结果可能不一样,而它也是MySql的默认隔离级别。

    4.串行化。

    这是数据库最高的隔离级别,这种级别下,事务“串行化顺序执行”,也就是一个一个排队执行。

    这种级别下,“脏读”、“不可重复读”、“幻读”都可以被避免,但是执行效率奇差,性能开销也最大,所以基本没人会用。

    4.注解

    5.集合

     5.1 hashcode作用?

     hashcode主要用于查找的快捷性,在散列存储结构中确定对象的存储地址.

    5.2 ArrayList原理?

    ArrayList底层数据结构是一个数组,数组元素类型为Object类型,对其操作底层都是基于数组的,

    线程不安全,可使用synchronied关键字保证代码安全.

     5.3 HashMap原理?

    map以key-value键值对进行数据存储. 当传入数据时先将key取出, 利用hash函数转换成hash值, 再用散列算法得到存入下标index.

    如果下标有数据用equal比较hash值是否相同, 再比较key值是否相同, 相同覆盖不同则存储.

    hashmap默认长度16, 达到上限自动扩容

     5.4 collection与collections区别?

    collection  是java.util下接口,集合结构父类

    collections是java.util下类,操作集合的静态方法

    5.5 ArrayList与LinkedList区别?

     ArrayList基于数组结构,LinkedList基于链表结构

    随机访问 ArrayList优于LinkedList

    新增删除 LinkedList优于ArrayList

    5.6 ArrayList与Vector区别?

    vector是线程安全的, Array不是, Vector效率比Array低.

    5.7 HashSet与HashMap区别?

    Set: 实现set接口, 存储对象, add加元素

    Map:实现map接口, 存储键值对 ,put加元素, 更快

    5.8 HashMap和HashTable区别?

    都实现map接口, hashmap线程不安全但比hashtable快, 单线程用HashMap多线程用HashTable

    5.9 数组和链表的区别?

    数组::将元素在内存中连续存放,每个元素占用内存相同,可以通过下标迅速访问数组任何元素。增加,刪除就会移动大量元素在内存中腾出空间,适用快速访问。

    链表: 链表中的元素在内存中不是顺序存储的,通过元素中指针联系在一起的,适用于增删。

  • 相关阅读:
    php 闭包 function use用法
    php序列号和反序列化
    [转]php composer使用
    hex编码,用途是什么,为什么需要hex编码呢?
    美术资源优化/LOD
    ASTC纹理压缩格式详解
    Elastic Stack之 Elasticsearch 6.7.1版本单机版安装、集群版安装
    使用datax将mysql数据同步到ES 附elasticsearchwriter插件
    Java1.8之Lambda表达式
    Java1.8之Lambda表达式、流Stream学习
  • 原文地址:https://www.cnblogs.com/chong-zuo3322/p/12684741.html
Copyright © 2011-2022 走看看