前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >秋招面经一(蚂蚁、招银)

秋招面经一(蚂蚁、招银)

作者头像
鹏-程-万-里
发布2020-10-10 10:06:12
5310
发布2020-10-10 10:06:12
举报
文章被收录于专栏:Java小白成长之路

本想着一次性全部放上来,但是最后发现内容还是有点多,最后想想还是分为5块儿放上来吧~如果有需要的小伙伴可以自取哈!

另外,面试的问题较多,有些问题过于复杂,我就没有把答案写上来,大家可以针对性的搜索答案即可。

有些问题,在多次面试冲重复出现,我就简单的进行合并了,大家按顺序看即可。


实习

蚂蚁金服

一面(2020-4-24)

1、对一个操作数进行多线程操作,如何保证不会出现结果的混乱

可以使用synchronize关键字,对操作数进行加锁,或者使用volatile关键字,使得变量具有可见性。

2、多线程相互之间如何通信?

线程之间的通信可以使用管道pipe进行通信,在Java中对应的就是pipedWriter和pipedReader进行通信,类似于生产者-消费者模式。

  • 信号量:信号量是一个计数器,可以用来控制多个线程对共享资源的访问.,它不是用于交换大批数据,而用于多线程之间的同步.它常作为一种锁机制,防止某进程在访问资源时其它进程也访问该资源.因此,主要作为进程间以及同一个进程内不同线程之间的同步手段.
  • 锁机制:包括互斥锁、条件变量、读写锁
    • 互斥锁提供了以排他方式防止数据结构被并发修改的方法。
    • 读写锁允许多个线程同时读共享数据,而对写操作是互斥的。
    • 条件变量可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。
  • 信号量机制(Semaphore):包括无名线程信号量和命名线程信号量
  • 信号机制(Signal):类似进程间的信号处理

线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制。

3、卡夫卡如何保证可靠性:一旦一个挂了,如何保证另一个开始另一个恢复?

kafka的每个分区都有多个副本,如果一个broker宕机了,zookeeper会自动选择另一个副本作为主副本。在选择从副本的时候,使用ISR优先的原则来完成选举。

4、有没有考虑本地缓存对jvm的影响?

本地缓存会占用内存,会影响jvm的可使用内存的大小。

二面(2020-4-27)

1、项目中,分布式部署kafka时,如果保证一个消息不会被多个消费者进行消费?

同一个消费者组内使用的是点到点,避免重复消费;

不同的消费者组之间,是订阅发布者模式。

每个主题内的消费者组,同组中的所有消费者不能订阅相同的分区。

2、tcp4次挥手?

TCP的报文格式如下所示:

3次握手过程如下:

  • 第一次握手:客户端发送给服务器建立连接的请求,然后自身进入syn-sent状态,此时有同步号标志位SYN=1,发送的序列长度seq=x,没有确认号。
  • 第二次握手:服务器接收到SYN=1,seq=x的数据报之后,可以了解到这个数据报是一个请求连接的数据报,然后服务器便向客户端进行响应,然后将自己的状态转换为SYN-RCVD。在响应给客户端的数据报中,依旧需要将同步位设置为SYN=1,ACK=1,并且设置对应的确认号ack=x+1,表示下一次客户端可以从x+1的位置开始传输数据,同时也将自己的数据报的长度写入数据报中,seq=y
  • 第三次握手:经过上面的两次握手之后,可以确保网络的通畅,并且建立了一个相对稳定的连接,彼此协商好了发送和接收的窗口大小等参数。此时客户端需要再次给服务器端,表示客户端已经接受到了服务器发送过来的确认连接信息,由于此时已经建立了连接,所以此次的数据包中不需要设置同步位SYN,根据第二次握手的数据报中的seq=y,可以告知服务器一个确认号ack=y+1。同时根据第二次握手的确认号ack=x+1,设置此次发送数据的起始位置为seq = x+1。

经过三次握手之后,客户端与服务器端的连接就建立好了,双方开始正常的发送数据。

为什么要有第三次握手?

假如没有第三次握手过程,仅有两次。可能会出现这么一种情况:客户端第一次发送请求,但是由于网络不通畅,很久还没有到达服务器端,此时客户端会以为数据报丢失,重新发送一个新的请求连接的数据报,然后服务器接收到第二次的连接请求后,就和客户端建立连接。

但是过了一段时间之后,客户端第一次发送的请求连接数据报到达了服务器端,服务器端会做出响应,给客户端发送一个确认报文,然后就以为与客户端建立了连接,开始等待客户端发送数据。

可是客户端已经与服务器端建立了连接,便不会响应服务端第二次发送过来的响应报文,那么服务器端就会以为建立了新的连接,一直等待客户端传送数据,使得服务器端处于浪费资源的状态。

四次挥手过程

  • 第一次挥手:客户端给服务器发送第一次挥手数据报,设置标志位FIN = 1 ,seq = u ,表示客户端请求释放连接。 然后客户端状态转换为FIN-WAIT1
  • 第二次挥手:服务器收到请求释放连接的请求后,做出响应,设置标志位ACK = 1 ,seq = v ,确认号根据第一次挥手请求的seq = u,此时设置为ack = u+1。此时关闭客户端到服务器端发送数据的通道,但是服务器依旧可以向客户端发送数据,此时服务器端的状态更改为CLOSE-WAIT客户端收到数据报之后,状态更改为FIN-WAIT2
  • 第三次挥手:当服务器端将最后的数据也发送完成之后,服务器向客户端发送一个释放连接的请求,标志位FIN=1 , ACK = 1,确认号依旧为ack = u+1 , seq设置为起始位置w。此时服务器状态转换为LAST-ACK
  • 第四次挥手:客户端收到数据报文后,给服务器端响应一个确认报文,此时的标志位ACK=1,seq = u+1 , ack = w+1。此时客户端也进入等待状态,等待一段时间之后,再关闭,改变状态为closed

为什么第四次挥手后,客户端不立即关闭?

假如第四次挥手的数据报在传输过程中丢失,那么服务器端将无法收到第四次挥手的报文,就会重新发送第三次挥手的报文给客户端,此时的客户端收到重新发送过来的挥手报文,会重新给服务器端发送第四次的挥手报文。

假如说客户端在发送完第四次挥手报文之后,立即关闭。那么上述情况发生之后,服务器端将无法收到关闭连接的确认请求,将会不断的向客户端发送第三次挥手请求,同时,客户端已经关闭,无法响应,那么服务器端将会一直处于LAST-ACK状态中,将永远无法释放此次的连接。

3、在客户端检测到服务器端进行了连接重置,一般是什么原因造成的?
4、数据库底层为什么要用B+树,B+树有什么优势?

B+树是把所有的数据都存储在叶子节点中,每个叶子节点都会有一个页表,对应着叶子节点中的每条数据的索引值。

B+树的优点是,高度低,每次在非叶子节点做判断的时候,就可以直接知道下一次要前往哪个子节点去。由于树的高度低,并且所有的数据都是存放在硬盘中,这样就会使得我们把数据从硬盘读取到内存中的次数较少,提高效率。

5、数据库如何保证事务的一致性的?

在数据库的底层,会有一个undo.log和一个redo.log,在宕机之后,会从这两个log文件中进行恢复操作。与此同时在innodb中还会有MVCC来保证并发性更改数据同步。

在mysql中使用wal的方式进行数据存储,所有的数据在写入之前,首先将命令写入到redo.log文件中。开机时,会检查磁盘中的文件与redo.log的文件中记录的数据是否一致。在使用undo.log文件的时候,使用的就是撤销操作,对每次的操作命令记录其对应的逆操作命令,比如:add命令,就对应着delete命令,在事务内部依次执行即可保证事务的原子性。

6、如何理解OS中的进程,java中的线程,还有一个协程?
  • 进程:进程是表示资源分配的基本单位,又是调度运行的基本单位。例如,用户运行自己的程序,系统就创建一个进程,并为它分配资源,包括各种表格、内存空间、磁盘空间、I/O设备等。然后,把该进程放人进程的就绪队列。进程调度程序选中它,为它分配CPU以及其它有关资源,该进程才真正运行。所以,进程是系统中的并发执行的单位。
  • 线程:线程是进程中执行运算的最小单位,亦即执行处理机调度的基本单位。如果把进程理解为在逻辑上操作系统所完成的任务,那么线程表示完成该任务的许多可能的子任务之一。例如,假设用户启动了一个窗口中的数据库应用程序,操作系统就将对数据库的调用表示为一个进程。假设用户要从数据库中产生一份工资单报表,并传到一个文件中,这是一个子任务;在产生工资单报表的过程中,用户又可以输人数据库查询请求,这又是一个子任务。这样,操作系统则把每一个请求――工资单报表和新输人的数据查询表示为数据库进程中的独立的线程。线程可以在处理器上独立调度执行,这样,在多处理器环境下就允许几个线程各自在单独处理器上进行。操作系统提供线程就是为了方便而有效地实现这种并发性。
  • 多线程调度:
    • 协同式(协程):线程的执行时间由线程本身来控制,只有当线程把自己的任务做完了,才会通知系统切换到另外的一个线程上去。
    • 抢占式:每个线程的使用时间由系统来分配,线程的切换不由线程本身来决定
7、java中如何结束线程的方式有哪些?

①使用标志位的方式使得整个线程运行完run方法

②使用interrupt()方法中断当前线程

③直接使用stop方法,但是这种方法目前已经被弃用,是一种安全的方法,类似于直接断电的方式

8、jvm中的垃圾回收算法有哪些?

标记复制,标记整理,标记清除

9、当客户端访问浏览器的时候,应该采取什么样的垃圾回收算法?
9、jvm的双亲委派机制?

具体的流程在下面的这种图中,当加载一个类的时候,首先是将其交给父类加载器进行加载,如果父类加载器无法加载,然后再依次向下进行传递。

在jvm规范中,只分为两类类加载器,第一类是系统类加载器:启动类加载器(由c编写)。第二类是用户类加载器:除了启动类加载器都属于这一类。

优势:

  • 防止重复加载同一个.class。通过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全。
  • 保证核心.class不能被篡改。通过委托方式,不会去篡改核心.clas,即使篡改也不会去加载,即使加载也不会是同一个.class对象了。
  • 不同的加载器加载同一个.class也不是同一个Class对象。这样保证了Class执行安全。
10、接口的保护限流机制如何实现? 比如规定一个接口1秒内只能进行5万次访问

在Redis中可以使用一个队列来实现限流操作。比如每来一次请求,查看队首的时间,如果队首时间与当前时间间隔超过1秒,则移除队首元素,把当前元素添加在尾部,如果间隔不到一秒,再判断队列中的请求个数,如果没有超过5万,则加入队列,否则阻塞等待,否则。

11、hashMap是线程不安全的,ConcurrentHashMap是线程安全的,如何保证的?

java中的免锁容器主要实现的原理是:对容器的修改可以与读取操作同时发生。

concurrentHashMap使用的是分段锁的技术,保证读取时可以有较高的速度,并在写的时候利用写时复制技术,保证整体的线程安全。

12、hashMap和treeMap的区别,分别适应什么情况下进行选择?

treeMap中的键值对是有序存储(此处的有序是指按照自然序进行排序)。

hashmap中是无序的。

13、hashMap中的hash算法如何避免键的冲突问题。

hash碰撞无论是什么算法都是无法完全避免的,只能使用好的hash算法来降低hash碰撞的次数。

当发生hash碰撞的时候,hashmap使用的是散列表(数组+链表)的方式来进行解决,在jdk1.8之后,还加入了红黑树来提升效率。

14、了解哪些互联网的大佬?

王坚(阿里云创始人),多隆,褚霸,吴翰清

15、平时学习的方式?

一面(来自朋友)

16、谈一下Arraylist和Linkedlist的区别?

ArrayList 底层实现就是数组,且ArrayList实现了RandomAccess,表示它能快速随机访问存储的元素,通过下标 index 访问,数组支持随机访问, 查询速度快, 增删元素慢; LinkedList 底层实现是链表, LinkedList 没有实现 RandomAccess 接口,链表支持顺序访问, 查询速度慢, 增删元素快.

17、Arraylist和Linkedlist查询和增删操作的时间复杂度分别是多少?

Arraylist 根据下标查询,顺序存储知道首个元素的地址,其他的位置很快就能确定,时间复杂度为O(1); Linkedlist 从首个元素开始查找,直到查找到第 i个位置,时间复杂度为O(n);

Arraylist插入指定位置元素,后面元素需要向后移动,时间复杂度为O(n); Linkedlist插入指定位置元素,直接指针操作(设置前驱结点和后驱节点)时间复杂度为O(1);

Arraylist删除指定位置元素,后面元素需要向前移动,时间复杂度为O(n); Linkedlist删除指定位置元素,直接指针操作(将前驱结点和后驱结点相连),时间复杂度O(1);

18、Arraylist底层实现是数组,容量不够怎么办?

容量不够,首先创建一个新的容量数组,再将原来数组复制到新的数组中去,释放旧数组。

19、Linklist查询时间复杂度O(n)有没有什么方法优化?

传进来的索引小于集合size/2就从头节点开始遍历查询,反之从尾节点反向遍历查询;

20、谈一下tcp协议和三次握手?

TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。数据传输时,应用程序向TCP层发送数据流,TCP就会将接受到的数据流切分成报文段(会根据当前网络环境来调整报文段的大小),然后经过下面的层层传递,最终传递给目标节点的TCP层。为了防止丢包,TCP协议会在数据包上标有序号,对方收到则发送ACK确认。未收到则重传。

这个步骤就是我们通常所说的TCP建立连接的三次握手。同时TCP会通过奇偶校验和的方式来校验数据传输过程中是否出现错误。

第一次握手:当客户端需要去建立连接时,客户端就会发送SYN包(seq=x)到服务器,然后客户端进入SYN_SEND的状态,代表已经发SYN包过去, 并且在等待服务器确认。此时ACK=0,SYN=1,这时候由于才第一次握手,所以没有ACK标志。第二次握手:服务器收到SYN包,就会进行确认,由上面的标志位介绍我们可以知道SYN是表示同步序号,这时候会使得ack=x+1, 然后服务器也会像客户端发送一个SYN包(seq=y),这时候也就是服务器会发送SYN+ACK包,来表示服务器确认到了客户端的一次握手并且二次握手建立,此时服务器进入SYN_RECV状态。此时SYN=1,ACK=1,这时候由于是第二次握手,所以就会有一个服务器给客户端的确认标志。第三次握手:客户端收到服务器的SYN+ACK包,然后就会像服务器发送确认包ACK(ack=k+1)和seq=x+1,等到这个包发送完毕之后,客户端和服务器就会进入ESTABLISHED状态,完成三次握手,而后就可以在服务端和客户端之间传输数据。此时SYN标志位已经不需要,因为当我们发送ACK标志位的时候代表三次握手成功,已经建立完连接了,接下来可以传送数据过去了。


提前批

招商银行

一面(2020-7-7)

二面(2020-714)

1、项目缓存中如何保证消息一直是最新的。

我们在发布或者修改一个帖子的时候,会使用kafka来监听,告诉elasticsearch进行写入操作,通过这种方式来保证我们elasticsearch可以进行实时的搜索。

2、kafka同一个消费者组如何保证不会重复消费。

kafka同时支持两种消息投递模式:

  • 对于消费者组内而言,所有消息会被均衡的投递给每一个消费者,即每条消息只会被一个消费者处理,相当于点对点模式
  • 对于不同的消费者组,消息会被广播给每一个消费者组,相当于发布、订阅模式
3、项目中的elasticsearch用什么做的索引

我们是将帖子的内容content和帖子的标题title作为索引。具体如下所示:

代码语言:javascript
复制
package com.nowcoder.community.entity;

import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.util.Date;

//@Document注解用于配置elasticSearch的内容,依次为:索引名称,类型,分片数量,副本数量
@Document(indexName = "discusspost", type = "_doc", shards = 6, replicas = 3)
public class DiscussPost {

    @Id
    private int id;

    @Field(type = FieldType.Integer)
    private int userId;

    //第二个analyzer,是存储拆分器,将存入的内容,尽可能查分成为多个词语
    //第三个属性searchAnalyzer,是搜索拆分器,智能的将搜索内容查分成具有较好语义的几个词语
    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
    private String title;

    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
    private String content;

    @Field(type = FieldType.Integer)
    private int type;

    @Field(type = FieldType.Integer)
    private int status;

    @Field(type = FieldType.Date)
    private Date createTime;

    @Field(type = FieldType.Integer)
    private int commentCount;

    @Field(type = FieldType.Double)
    private Double score;

    @Override
    public String toString() {
        return "DiscussPost{" +
                "id=" + id +
                ", userId='" + userId + '\'' +
                ", title='" + title + '\'' +
                ", content='" + content + '\'' +
                ", type=" + type +
                ", status=" + status +
                ", createTime=" + createTime +
                ", commentCount=" + commentCount +
                ", score=" + score +
                '}';
    }
}
3、线程池的几个参数,会一开始就创建核心线程数量么?

线程池一开始不会创建核心线程数量,而是没来一个任务,就创建一个线程。

这里需要注意一点,在线程池中的线程数量尚未达到核心线程数量之前,每次来一个任务,不管此时有没有空闲的可用线程,线程池都会新创建一个线程来给新任务使用。

线程池创建的7大参数我们直接找到源码,如下所示:

代码语言:javascript
复制
    /**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @param threadFactory the factory to use when the executor
     *        creates a new thread
     * @param handler the handler to use when execution is blocked
     *        because the thread bounds and queue capacities are reached
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue}
     *         or {@code threadFactory} or {@code handler} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = (System.getSecurityManager() == null)
            ? null
            : AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }
4、hashMap数据结构,不安全如何保证的。

(1)数组+链表+红黑树。

(2)安全问题有两个:

  • A、B线程都去put值的时候,发生hash碰撞,然后同时将对应的数组中的next指针指向自己,这样就会导致有一个线程的插入值被覆盖
  • 在对数组进行重新resize的时候,A、B线程都在进行transfer方法,在transfer方法之后只会有一个线程对结果生效,假如A、B线程都对resize之后的链表中插入了值,那么将会导致有一个线程插入的值失效。

(3)死锁问题

在1.8之前,在使用transfer的时候使用头插法,也就是链表的顺序会翻转,这样在A线程插入到一半时临时挂起,此时B线程同时也去更改,这样就会产生一种循环链表的问题。造成最后的死循环。

在jdk1.8之后,改用了尾插法,使得转移前后链表中的元素顺序不会发生改变,所以就解决了死锁问题。

5、concurrentHashMap的如何保证安全的

1.7版本:segment+hashEntrys

1.8版本:散列表+红黑树

首先使用分段锁+cas算法+volatile,实现整体的不加锁。在put方法的时候,首先检查是否已经初始化,如果没有初始化,则进行初始化工作,然后使用rehash对键的hash值进行再散列,然后使用(n-1)& hash值,获取元素所在table的位置。

get方法不加锁,直接获取,我们可以发现,Node节点是重写的,设置了volatile关键字修饰,致使它每次获取的都是最新设置的值。

代码语言:javascript
复制
static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    volatile V val;
    volatile Node<K,V> next;

    Node(int hash, K key, V val) {
        this.hash = hash;
        this.key = key;
        this.val = val;
    }
    ....
}

一面(来自朋友)

1、网络传输层和应用层分别有哪些协议?以及之间的区别

网络传输层:TCP/UDP

应用层:http/dns/stmp/pop3

2、http有哪些方法

https://www.cnblogs.com/yinrw/p/10694474.html

  • get:GET方法用于使用给定的URI从给定服务器中检索信息,即从指定资源中请求数据。使用GET方法的请求应该只是检索数据,并且不应对数据产生其他影响。GET请求是可以缓存的,我们可以从浏览器历史记录中查找到GET请求,还可以把它收藏到书签中;且GET请求有长度限制,仅用于请求数据(不修改)。 【注】因GET请求的不安全性,在处理敏感数据时,绝不可以使用GET请求。 在GET请求的URL中发送查询字符串(名称/值对),需要这样写: /test/demo_form.php?name1=value1&name2=value2
  • post:POST方法用于将数据发送到服务器以创建或更新资源,它要求服务器确认请求中包含的内容作为由URI区分的Web资源的另一个下属。POST请求永远不会被缓存,且对数据长度没有限制;我们无法从浏览器历史记录中查找到POST请求。
  • head:HEAD方法与GET方法相同,但没有响应体,仅传输状态行和标题部分。这对于恢复相应头部编写的元数据非常有用,而无需传输整个内容。
  • put:PUT方法用于将数据发送到服务器以创建或更新资源,它可以用上传的内容替换目标资源中的所有当前内容。它会将包含的元素放在所提供的URI下,如果URI指示的是当前资源,则会被改变。如果URI未指示当前资源,则服务器可以使用该URI创建资源。
  • delete:DELETE方法用来删除指定的资源,它会删除URI给出的目标资源的所有当前内容。
  • connect:CONNECT方法用来建立到给定URI标识的服务器的隧道;它通过简单的TCP / IP隧道更改请求连接,通常实使用解码的HTTP代理来进行SSL编码的通信(HTTPS)。
  • options:OPTIONS方法用来描述了目标资源的通信选项,会返回服务器支持预定义URL的HTTP策略。
  • trace:TRACE方法用于沿着目标资源的路径执行消息环回测试;它回应收到的请求,以便客户可以看到中间服务器进行了哪些(假设任何)进度或增量。
3、Restful接口你知道吗?

按照请求的目的的不同,我们将每种功能的请求区分开,比如使用get请求做索引,put请求刷新,post请求做增加等等

4、Cookie和Session的区别?cookie和token有什么区别?

cookie存放在客户端,不安全,存量小,

session存放在服务器端,安全,存量大

token将用户信息进行加密作为令牌进行网络传输

5、MyBatis框架和面向对象的ORM的数据库插件的区别?

http://www.mybatis.cn/archives/764.html

ORM是Object和Relation之间的映射,包括Object->Relation和Relation->Object两方面。Hibernate是个完整的ORM框架,而MyBatis完成的是Relation->Object,也就是其所说的Data Mapper Framework。

JPA是ORM框架标准,主流的ORM框架都实现了这个标准。MyBatis没有实现JPA,它和ORM框架的设计思路不完全一样。MyBatis是拥抱SQL,而ORM则更靠近面向对象,不建议写SQL,实在要写,则推荐你用框架自带的类SQL代替。MyBatis是SQL映射框架而不是ORM框架,当然ORM和MyBatis都是持久层框架。

6、Redis为什么是单线程的?解释一下Redis的多路复用?多路复用存入格式为什么更好。
7、线程和进程的区别

进程属于系统中的概念,属于操作系统分配给每个执行程序的最小资源单位,一段执行代码运行起来之后叫做进程。进程中包括了系统的内存空间,寄存器等等信息。

线程属于进程中的最小执行单元,一个进程包括有多个线程,线程是除了进程中的内存空间,其他变量信息以外的东西。

8、Java多线程了解哪些类和关键字?解释一下具体

创建方式:Thread,Runnable,Callable

9、 Volatile是干嘛的?synchronized在哪些地方可以使用?
  • volatile的特性:
  • 可见性:每次使用数据前,从内存中读取到自己的工作空间中。
  • 禁止重排序:对使用volatile关键字的变量在操作的前后会加内存屏障,达到禁止指令重排序的效果
  • 不保证原子性:
  • synchronized
    • 可以在方法内部的代码块中:此时在字节码层面上会有一个monitor变量来记录当前代码块是否有线程在使用,如下反编译的部分代码 3: monitorenter //进入同步方法 //..........省略其他 15: monitorexit //退出同步方法
    • 修饰整个方法:在字节码层面上,在方法的头部增加了一个标志位ACC_SYNCHRONIZED,每当有线程进入的时候,会首先检查该标志位是否已经被访问 public synchronized void syncTask(); descriptor: ()V //方法标识ACC_PUBLIC代表public修饰,ACC_SYNCHRONIZED指明该方法为同步方法 flags: ACC_PUBLIC, ACC_SYNCHRONIZED Code: stack=3, locals=1, args_size=1 0: aload_0 1: dup 2: getfield #2 // Field i:I 5: iconst_1 6: iadd 7: putfield #2 // Field i:I 10: return LineNumberTable: line 12: 0 line 13: 10
10、 Java有几类线程池?

总共4类,如下所示:

代码语言:javascript
复制
ExecutorService service = Executors.newFixedThreadPool(5);// 固定容量的线程池
ExecutorService service = Executors.newSingleThreadExecutor();// 容量为1的线程
ExecutorService service = Executors.newCachedThreadPool();//根据当前任务量自动调节池中线程数

ScheduledExecutorService service = Executors.newScheduledThreadPool(5);//定时任务的线程池
11、死锁的四个必要条件。
  • 资源互斥条件
  • 请求与保持条件
  • 不可抢占
  • 循环等待
12、String是线程安全的吗?ArrayList是线程安全的吗?

String 安全,被final修饰,当我们写如下代码的时候:

代码语言:javascript
复制
String a = "anc";
String b = "efg";
String c = a + b;

上面的代码将两个字符串相连时,底层是使用了StringBuilder类来进行转换。

ArrayList不安全,可以使用CopyOnWriteArrayList这个类是安全的。

13、线程同步的知识:多线程怎么协作?子线程如果想要返回数据给父线程(Java具体类return),对一个子线程中断会直接响应吗(在sleep和不在sleep时各有什么响应)

线程通信方式:

  • 锁机制
  • 信号量机制
  • 信号机制
  • volatile关键字
  • wait/notify
14、MySQL的引擎你了解哪些?

两种。myisam和innodb

15、Innodb的索引用的是什么?索引的数据结构是什么?B+树。B+树的特点?叶子节点之间还有什么特点?
16、A和B建立一个联合索引,什么规则?where A = *** and B like *** and C = ***这段联合索引哪些位置会用到索引?

只有A = *** 会使用到

17、四种隔离级别,分别解决了什么问题?幻读解决了什么问题,幻读用什么锁技术来解决?

隔离级别:

  • 读未提交:什么问题都没解决
  • 读已提交:解决脏读问题
  • 可重复读:解决不可重复读
  • 序列化:解决幻读

幻读使用的是间隙锁:gap lock + next key lock 解决

18、MySQL调优的所有手段?尽可能的说
19、拆分表一般怎么拆?有两种方法
20、索引建多了会带来什么问题?

因为每次都要更新索引,时间复杂度较大,占用内存较多。会额外的增加IOP频率

21、一张表有性别和年龄两个字段,要查询每个性别的平均年龄。这个SQL怎么写?涉及到SQL的一个关键字
22、Spring用过哪些设计模式?有哪些?

https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485303&idx=1&sn=9e4626a1e3f001f9b0d84a6fa0cff04a&chksm=cea248bcf9d5c1aaf48b67cc52bac74eb29d6037848d6cf213b0e5466f2d1fda970db700ba41&token=1667678311&lang=zh_CN#rd

单例模式,代理模式,工厂模式、模板方法模式、观察者

23、Java的HashSet底层是怎么实现的?

使用的是hashMap进行实现的

24、HashMap的key存的是什么?

HashCode的String值

25、写一个快排的代码。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java小白成长之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 实习
    • 蚂蚁金服
      • 一面(2020-4-24)
      • 二面(2020-4-27)
      • 一面(来自朋友)
  • 提前批
    • 招商银行
      • 一面(2020-7-7)
      • 二面(2020-714)
      • 一面(来自朋友)
相关产品与服务
云服务器
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档