pdd 面试准备

目录

mysql索引?为什么用B+树?

网络IO模型?什么是多路复用IO?select和epoll的差别?select具体过程?

java类加载机制?双亲委派模型的好处?

进程和线程的区别?线程是不是越多越好,为什么?***作系统怎么调度的,调度算法?java中cpu调度是线程还是进程?

数据库事务?隔离级别?

java线程变量怎么实现的?内存模型?

手撕代码

用数组模拟循环链表

堆排序实现

数据库索引?B+树?为什么要建索引?什么样的字段需要建索引,建索引的时候一般考虑什么?索引会不会使插入、删除***作效率变低,怎么解决(分表***作)

数据库事务特点?事务隔离级别?项目中的事务实现?脏读、不可重复读、幻读各举个例子?

Spring bean的生命周期?默认创建的模式是什么?不想单例怎么办?设计模式,单例模式,怎么保证线程安全?锁效率太低,怎么提高效率?CAS?CAS本质是什么?什么是原子性?Compare and Swap两步***作,为什么能保证原子性(涉及到CPU指令)?分布式锁?

还有什么设计模式?工厂模式有几种,都讲讲?简单工厂模式和工厂方法有什么差别?

 

数据库表怎么设计的?数据库范式?设计的过程中需要注意什么?enum类型的值一般怎么存?如果有一个十几位的小数为了不丢失精度怎么存?tinyint几个字节,int几个字节?


链接:https://www.nowcoder.com/discuss/124749

 

mysql索引?为什么用B+树?

与二叉树相比 
二叉树相比于顺序查找的确减少了查找次数,但是在最坏情况下,二叉树有可能退化为顺序查找。而且就二叉树本身来说,当数据库的数据量特别大时,其层数也将特别大。二叉树的高度一般是log_2^n,B树的高度是log_t^((n+1)/2) + 1,其高度约比B树大lgt倍。n是节点总数,t是树的最小度数。

与B树相比 
B树在提高IO性能的同时,并没与解决元素遍历时效率低下的问题,正是为了解决这个问题,B+数应运而生。B+数只需遍历叶子节点即可实现整棵树的遍历,而B树必须使用中序遍历按序扫库,B+树支持范围查询非常方便。这才是数据库选用B+树的主要原因。
--------------------- 
作者:PetrichorKe 
原文:https://blog.csdn.net/qq_38038480/article/details/81738079 

AVL树

(1)简介

AVL树是带有平衡条件的二叉查找树,一般是用平衡因子差值判断是否平衡并通过旋转来实现平衡,左右子树树高不超过1,和红黑树相比,它是严格的平衡二叉树,平衡条件必须满足(所有节点的左右子树高度差不超过1)。不管我们是执行插入还是删除操作,只要不满足上面的条件,就要通过旋转来保持平衡,而旋转是非常耗时的,由此我们可以知道AVL树适合用于插入删除次数比较少,但查找多的情况。 

红黑树

(1)简介

一种二叉查找树,但在每个节点增加一个存储位表示节点的颜色,可以是red或black。通过对任何一条从根到叶子的路径上各个节点着色的方式的限制,红黑树确保没有一条路径会比其它路径长出两倍。它是一种弱平衡二叉树(由于是若平衡,可以推出,相同的节点情况下,AVL树的高度低于红黑树),相对于要求严格的AVL树来说,它的旋转次数变少,所以对于搜索、插入、删除操作多的情况下,我们就用红黑树。

(2)性质

1、每个节点非红即黑; 
2、根节点是黑的; 
3、每个叶节点(叶节点即树尾端NULL指针或NULL节点)都是黑的; 
4、如果一个节点是红的,那么它的两儿子都是黑的; 
5、对于任意节点而言,其到叶子点树NULL指针的每条路径都包含相同数目的黑节点; 
6、每条路径都包含相同的黑节点;

 

B/B+树

说了上述的三种树:二叉查找树、AVL和红黑树,似乎我们还没有摸到MySQL为什么要使用B+树作为索引的实现,不要急,接下来我们就先探讨一下什么是B树。

(1)简介

我们在MySQL中的数据一般是放在磁盘中的,读取数据的时候肯定会有访问磁盘的操作,磁盘中有两个机械运动的部分,分别是盘片旋转和磁臂移动。盘片旋转就是我们市面上所提到的多少转每分钟,而磁盘移动则是在盘片旋转到指定位置以后,移动磁臂后开始进行数据的读写。那么这就存在一个定位到磁盘中的块的过程,而定位是磁盘的存取中花费时间比较大的一块,毕竟机械运动花费的时候要远远大于电子运动的时间。当大规模数据存储到磁盘中的时候,显然定位是一个非常花费时间的过程,但是我们可以通过B树进行优化,提高磁盘读取时定位的效率。

为什么B类树可以进行优化呢?我们可以根据B类树的特点,构造一个多阶的B类树,然后在尽量多的在结点上存储相关的信息,保证层数尽量的少,以便后面我们可以更快的找到信息,磁盘的I/O操作也少一些,而且B类树是平衡树,每个结点到叶子结点的高度都是相同,这也保证了每个查询是稳定的。

总的来说,B/B+树是为了磁盘或其它存储设备而设计的一种平衡多路查找树(相对于二叉,B树每个内节点有多个分支),与红黑树相比,在相同的的节点的情况下,一颗B/B+树的高度远远小于红黑树的高度(在下面B/B+树的性能分析中会提到)。B/B+树上操作的时间通常由存取磁盘的时间和CPU计算时间这两部分构成,而CPU的速度非常快,所以B树的操作效率取决于访问磁盘的次数,关键字总数相同的情况下B树的高度越小,磁盘I/O所花的时间越少。

为什么说B+树比B树更适合数据库索引?

1、 B+树的磁盘读写代价更低:B+树的内部节点并没有指向关键字具体信息的指针,因此其内部节点相对B树更小,如果把所有同一内部节点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了。

2、B+树的查询效率更加稳定:由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

3、由于B+树的数据都存储在叶子结点中,分支结点均为索引,方便扫库,只需要扫一遍叶子结点即可,但是B树因为其分支结点同样存储着数据,我们要找到具体的数据,需要进行一次中序遍历按序来扫,所以B+树更加适合在区间查询的情况,所以通常B+树用于数据库索引。

 

总结  要对查找的方式进行优化,熟悉的二分查找,二叉树可以把速度提升到O(log(n,2)),查询的瓶颈在于树的深度,最坏的情况要查找到二叉树的最深层,由于,每查找深一层,就要访问更深一层的索引文件。在多达数G的索引文件中,这将是很大的开销。所以,尽量把数据结构设计的更为‘矮胖’一点就可以减少访问的层数。在众多的解决方案中,B-/B+树很好的适合。B-树定义具体可以查阅,简而言之就是中间节点可以多余两个子节点,而且中间的元素可以是一个域。相比B-树,B+树的父节点也必须存在于子节点中,是其中最大或者最小元素,B+树的节点只存储索引key值,具体信息的地址存在于叶子节点的地址中。这就使以页为单位的索引中可以存放更多的节点。减少更多的I/O支出。因此,B+树成为了数据库比较优秀的数据结构,MySQL中MyIsAM和InnoDB都是采用的B+树结构。不同的是前者是非聚集索引,后者主键是聚集索引,所谓聚集索引是物理地址连续存放的索引,在取区间的时候,查找速度非常快,但同样的,插入的速度也会受到影响而降低。聚集索引的物理位置使用链表来进行存储。

引自 https://www.cnblogs.com/tiancai/p/9024351.html

 

网络IO模型?什么是多路复用IO?select和epoll的差别?select具体过程?

五种网络模型

第一阶段:等待数据 wait for data

第二阶段:从内核复制数据到用户 copy data from kernel to user

1阻塞I/Oblocking I/O: 

就是我们常见的socket,监听端口收到消息进行处理,并把结果返回给客户端

执行I/O操作完成前会一直进行等待,不会将控制权交给程序。套接字默认为阻塞模式

应用程序调用一个IO函数,导致应用程序阻塞,等待数据准备好。 如果数据没有准备好,一直等待….数据准备好了,从内核拷贝到用户空间,IO函数返回成功指示,程序继续执行
--------------------- 

2、非阻塞I/Ononblocking I/O

 

非阻塞IO通过进程反复调用IO函数,与阻塞不同的是,调用IO函数后,内核会立刻返回一个错误的接口,该进程会不断去调用查询结果的函数recv(),直到收到正确的结果,在这个过程中进程是阻塞的

非阻塞模式套接字与阻塞模式套接字相比,不容易使用。使用非阻塞模式套接字,需要编写更多的代码,但是,非阻塞套接字在控制建立的多个连接,在数据的收发量不均,时间不定时,明显具有优势

 

3、I/O复用模型 I/O multiplexing (select and poll)

主要是select和epoll;对一个IO端口,两次调用,两次返回,比阻塞IO并没有什么优越性;关键是能实现同时对多个IO端口进行监听;
I/O复用模型会用到select、poll、epoll函数,这几个函数也会使进程阻塞,但是和阻塞I/O所不同的的,这两个函数可以同时阻塞多个I/O操作。而且可以同时对多个读操作,多个写操作的I/O函数进行检测,直到有数据可读或可写时,才真正调用I/O操作函数

4、信号驱动I/O signal driven I/O (SIGIO)

首先我们允许套接口进行信号驱动I/O,并安装一个信号处理函数,进程继续运行并不阻塞。当数据准备好时,进程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据


5、异步I/O模型 asynchronous I/O (the POSIX aio_functions)

当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者的输入输出操作
--------------------- 
作者:zecoo 
来源:CSDN 
原文:https://blog.csdn.net/king866/article/details/53870086 
版权声明:本文为博主原创文章,转载请附上博文链接!

 

select、poll和epoll的区别和 IO多路复用模型讲解

 

select,poll,epoll都是IO多路复用的机制。I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。

此时需知道两个概念:

所谓阻塞方式block,顾名思义,就是进程或是线程执行到这些函数时必须等待某个事件的发生,如果事件没有发生,进程或线程就被阻塞,函数不能立即返回。

所谓非阻塞方式non-block,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有发生,则返回一个代码来告知事件未发生,而进程或线程继续执行,所以效率较高。

select

 

 

一.select()的机制中提供一fd_set的数据结构,实际上是一long类型的数组, 每一个数组元素都能与一打开的文件句柄(不管是Socket句柄,还是其他 文件或命名管道或设备句柄)建立联系,建立联系的工作由程序员完成, 当调用select()时,由内核根据IO状态修改fd_set的内容,由此来通知执行了select()的进程哪一Socket或文件可读或可写。主要用于Socket通信当中。

select使用:它能够监视我们需要监视的文件描述符的变化情况——读写或是异常。准备就绪的描述符数,若超时则返回0,若出错则返回-1。

1.如果一个发现I/O有输入,读取的过程中,另外一个也有了输入,这时候不会产生任何反应.这就需要你的程序语句去用到select函数的时候才知道有数据输入。

2.程序去select的时候,如果没有数据输入,程序会一直等待(阻塞时),直到有数据为止,也就是程序中无需循环和sleep。

二.poll:

 

poll的实现和select非常相似,只是描述fd集合的方式不同,poll使用pollfd结构而不是select的fd_set结构,其他的都差不多。

监视描述符个数无上限;

1.最大描述符+1,个数由fds数组决定。

2.监视事件与返回后事件状态反生分离,调用前后不需重置。

3.调用后轮询检测监视事件是否发生。

4.系统与用户数据拷贝:使用copy_from_user从用户空间拷贝fds到内核空间

 

三.epoll.

 

epoll是linux内核为处理大批量文件描述符而作了改进的poll,是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中中只有少量活跃的情况下的系统CPU利用率。另一点原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行了。epoll除了提供select/poll那种IO事件的水平触发(Level Triggered)外,还提供了边缘触发(Edge Triggered),这就使得用户空间程序有可能缓存IO状态,减少epoll_wait/epoll_pwait的调用,提高应用程序效率。

 

 

epoll特点:

1.epoll和select和poll的调用接口上的不同。

select和poll都只提供了一个函数——select或者poll函数。而epoll提供了三个函数,epoll_create,epoll_ctl和epoll_wait,epoll_create是创建一个epoll句柄;epoll_ctl是注册要监听的事件类型;epoll_wait则是等待事件的产生。

 

2.使用mmap加速内核与用户空间的消息传递。

对于select和poll函数的系统与内核每次调用时的数据拷贝:epoll是通过内核与用户空间mmap同一块内存实现的,在epoll_ctl函数中:每次注册新的事件到epoll句柄中时(在epoll_ctl中指定EPOLL_CTL_ADD),会把所有的fd拷贝进内核,而不是在epoll_wait的时候重复拷贝。epoll保证了每个fd在整个过程中只会拷贝一次。

3.调用后不需轮询判断描述符事件是否就绪。

对于select和poll函数每次调用后轮询检测事件是否发生:epoll的解决方案不像select或poll一样每次都把current轮流加入fd对应的设备等待队列中,而只在epoll_ctl时把current挂一遍(这一遍必不可少)并为每个fd指定一个回调函数,当设备就绪,唤醒等待队列上的等待者时,就会调用这个回调函数,而这个回调函数会把就绪的fd加入一个就绪链表)。epoll_wait的工作实际上就是在这个就绪链表中查看有没有就绪的fd(利用schedule_timeout()实现睡一会,判断一会的效果)。

4.监视描述符没有个数上限。

epoll没有这个限制,它所支持的FD上限是最大可以打开文件的数目,这个数字一般远大于2048,注:在1GB内存的机器上大约是10万左右,具体数目可以cat /proc/sys/fs/file-max察看,一般来说这个数目和系统内存关系很大。

5.IO效率不随FD数目增加而线性下降。

传统的select/poll另一个致命弱点就是当你拥有一个很大的socket集合,不过由于网络延时,任一时间只有部分的socket是“活跃”的,但是select/poll每次调用都会线性扫描全部的集合,导致效率呈现线性下降。但是epoll不存在这个问题,它只会对“活跃”的socket进行操作---这是因为在内核实现中epoll是根据每个fd上面的callback函数实现的。只有“活跃”的socket才会主动的去调用 callback函数,其他idle状态socket则不会。

epoll对于select和poll相比,显著优点是:

(1)select,poll实现需要自己不断轮询所有fd集合,直到设备就绪,期间可能要睡眠和唤醒多次交替。而epoll其实也需要调用epoll_wait不断轮询就绪链表,期间也可能多次睡眠和唤醒交替,但是它是设备就绪时,调用回调函数,把就绪fd放入就绪链表中,并唤醒在epoll_wait中进入睡眠的进程。虽然都要睡眠和交替,但是select和poll在“醒着”的时候要遍历整个fd集合,而epoll在“醒着”的时候只要判断一下就绪链表是否为空就行了,这节省了大量的CPU时间。这就是回调机制带来的性能提升。

(2)select,poll每次调用都要把fd集合从用户态往内核态拷贝一次,并且要把current往设备等待队列中挂一次,而epoll只要一次拷贝,而且把current往等待队列上挂也只挂一次(在epoll_wait的开始,注意这里的等待队列并不是设备等待队列,只是一个epoll内部定义的等待队列)。这也能节省不少的开销。

 

poll和epoll适用于关心描述符个数多的应用程序。其中epoll对于每次只有很少描述符就绪很有优势(采用回调机制监测描述符就绪)。

 

原文:https://blog.csdn.net/ligupeng7929/article/details/79491713
版权声明:本文为博主原创文章,转载请附上博文链接!

java类加载机制?双亲委派模型的好处?

 

启动类加载器 Bootstrap ClassLoader:加载<JAVA_HOME>\lib目录下核心库

扩展类加载器 Extension ClassLoader:加载<JAVA_HOME>\lib\ext目录下扩展包

应用程序类加载器 Application ClassLoader:  加载用户路径(classpath)上指定的类库

1.当Application ClassLoader 收到一个类加载请求时,他首先不会自己去尝试加载这个类,而是将这个请求委派给父类加载器Extension ClassLoader去完成。  

2.当Extension ClassLoader收到一个类加载请求时,他首先也不会自己去尝试加载这个类,而是将请求委派给父类加载器Bootstrap ClassLoader去完成。  

3.如果Bootstrap ClassLoader加载失败(在<JAVA_HOME>\lib中未找到所需类),就会让Extension ClassLoader尝试加载。  

4.如果Extension ClassLoader也加载失败,就会使用Application ClassLoader加载。  

5.如果Application ClassLoader也加载失败,就会使用自定义加载器去尝试加载。  

6.如果均加载失败,就会抛出ClassNotFoundException异常。 

 双亲委派模型的实现过程:



实现双亲委派模型的代码都集中在java.lang.ClassLoader的loadClass()方法中:  
首先会检查请求加载的类是否已经被加载过;  
若没有被加载过:  
递归调用父类加载器的loadClass();  
父类加载器为空后就使用启动类加载器加载;  
如果父类加载器和启动类加载器均无法加载请求,则调用自身的加载功能。
 


双亲委派模型的优点:

Java类伴随其类加载器具备了带有优先级的层次关系,确保了在各种加载环境的加载顺序。  

保证了运行的安全性,防止不可信类扮演可信任的类。

    当一个类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父类去完成,每一个层次类加载都是如此,因此所有的加载请求都应该传送到启动类加载器中,只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径里找不到这个所需要加载的类),子类加载器才会尝试自己去加载
--------------------- 
原文:http://blog.csdn.net/inspiredbh/article/details/74889654

 

进程和线程的区别?线程是不是越多越好,为什么?***作系统怎么调度的,调度算法?java中cpu调度是线程还是进程?

 

根本区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位

根本区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位

在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。

所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)

内存分配方面:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。

包含关系:没有线程的进程可以看做是单线程的,如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。


--------------------- 
作者:kingdoooom 
原文:https://blog.csdn.net/kuangsonghan/article/details/80674777 

java中cpu调度是线程还是进程?

线程是进程的实体,属于进程,是CPU调度和分派的基本单位

具体可以看大佬博客:https://blog.csdn.net/ITermeng/article/details/76071049

先来先服务调度算法(FCFS):

就是按照各个作业进入系统的自然次序来调度作业。这种调度算法的优点是实现简单,公平。其缺点是没有考虑到系统中各种资源的综合使用情况,往往使短作业的用户不满意,因为短作业等待处理的时间可能比实际运行时间长得多。


短作业优先调度算法 (SPF):

就是优先调度并处理短作业,所谓短是指作业的运行时间短。而在作业未投入运行时,并不能知道它实际的运行时间的长短,因此需要用户在提交作业时同时提交作业运行时间的估计值。


最高响应比优先算法(HRN):

FCFS可能造成短作业用户不满,SPF可能使得长作业用户不满,于是提出HRN,选择响应比最高的作业运行。响应比=1+作业等待时间/作业处理时间。


基于优先数调度算法(HPF):

每一个作业规定一个表示该作业优先级别的整数,当需要将新的作业由输入井调入内存处理时,优先选择优先数最高的作业。
--------------------- 
作者:wanhf11 
原文:https://blog.csdn.net/qq_17612199/article/details/52416702 
 

 

 

数据库事务?隔离级别?

 

数据库的几种隔离级别:

  • READ UNCOMMITTED(读未提交数据):允许事务读取未被其他事务提交的变更数据,会出现脏读、不可重复读和幻读问题。
  • READ COMMITTED(读已提交数据):只允许事务读取已经被其他事务提交的变更数据,可避免脏读,仍会出现不可重复读和幻读问题。
  • REPEATABLE READ(可重复读):确保事务可以多次从一个字段中读取相同的值,在此事务持续期间,禁止其他事务对此字段的更新,可以避免脏读和不可重复读,仍会出现幻读问题。
  • SERIALIZABLE(序列化):确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止其他事务对该表执行插入、更新和删除操作,可避免所有并发问题,但性能非常低。

Oracle支持两种事务隔离级别:

  READ COMMITTED(读已提交数据)(默认事务隔离级别)

     SERIALIZABLE  (序列化)

MySQL支持四种事务隔离级别

其中REPEATABLE READ为默认事务隔离级别。

 

数据库事务的特性:原子性、一致性、隔离性、持久性

  • 原子性:事务的原子性指的是,事务中包含的程序作为数据库的逻辑工作单位,它所做的对数据修改操作要么全部执行,要么完全不执行,这种特性称为原子性。(简单地说就是,几个对于数据库的操作要么全执行,要么全不执行,即同时成功起作用或同时失败没影响)
  • 一致性:事务一致性值得是在一个事务执行之前和执行之后数据库都必须处于一致性状态(中途是否一致不用管),这种特性称为一致性。(如果数据库的状态满足所有的完整性约束,就说该数据库是一致的。一致性处理数据库中对所有语义的保护。如:客户K1要向客户K2转账,K1账户减少的金额就是K2账户增加的金额,在转账之前K1和K2账户的金额之和与转账之后K1和K2账户的金额之和是一样的,在转账期间可能不满足这种一致性,但事务前后是数据库数据是一致的)
  • 隔离性:隔离性指的是并发的事务是相互隔离的。(一个事务内部的操作及正在操作的数据必须封装起来,不被其它企图进行修改的事务看到)
  • 持久性:持久性指当系统或介质发生故障时,确保已提交的更新不能丢失。(一个事务提交,DBMS保证它对数据库中数据的改变应该是永久性的,可以经受任何系统故障,持久性通过数据库备份和恢复来保证)

原文   :https://www.cnblogs.com/ForeverLover/p/4866354.html

 

 

java线程变量怎么实现的?内存模型?

https://blog.csdn.net/wengcheng_k/article/details/78917179

这里提到的共享内存模型指的就是Java内存模型(简称JMM),JMM决定一个线程对共享变量的写入何时对另一个线程可见。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:(线程——工作内存——主内存)

线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。

线程A与线程B之间如要通信的话,必须要经历下面2个步骤:

1. 首先,线程A把本地内存A中更新过的共享变量刷新到主内存中去。
2. 然后,线程B到主内存中去读取线程A之前已更新过的共享变量。 


--------------------- 
作者:Heaven-Wang 
原文:https://blog.csdn.net/suifeng3051/article/details/52611310 

Java多线程实现的方式有四种

1.继承Thread类,重写run方法
2.实现Runnable接口,重写run方法,实现Runnable接口的实现类的实例对象作为Thread构造函数的target
3.通过Callable和FutureTask创建线程
4.通过线程池创建线程

前面两种可以归结为一类:无返回值,原因很简单,通过重写run方法,run方式的返回值是void,所以没有办法返回结果 
后面两种可以归结成一类:有返回值,通过Callable接口,就要实现call方法,这个方法的返回值是Object,所以返回的结果可以放在Object对象中
--------------------- 
原文:https://blog.csdn.net/u011480603/article/details/75332435 

 

 

手撕代码

用数组模拟循环链表

堆排序实现

 

 

 

数据库索引?B+树?为什么要建索引?什么样的字段需要建索引,建索引的时候一般考虑什么?索引会不会使插入、删除***作效率变低,怎么解决(分表***作)

分库分表

最开始一般都选择垂直拆分.
比如电商网站,可能按照家电,图书,母婴等商品分类进行拆分.
这样做的好处是拆分简单,并且没有破坏数据库事务.

但是随着业务的增长,比如图书分类的订单数据表已经到达了10个T的规模.
就需要考虑做水平拆分了.把逻辑上一个表的数据,分别存放到不同的数据库服务器.
水平拆分的好处是
    多个数据库服务器分担CPU,内存,网络带宽的压力.
    多个数据库服务器分担备份、恢复的压力.
缺点是
    破坏了原生的数据库事务.如果使用分布式事务,则会拖累数据库性能.
    增加了运维管理的负担.原来管一台服务器就行了,现在得管一堆服务器.

水平拆分的三种主要方式
1.Hash拆分.比如按照 userId mod 64.将数据分布在64个服务器上
2.范围拆分.比如每台服务器计划存放一个亿的数据,先将数据写入服务器A.一旦服务器A写满,则将数据写入服务器B,以此类推.
这种方式的好处是扩展方便.数据在各个服务器上分布均匀.
3.路由表.自定义分布方式.

 

数据库事务特点?事务隔离级别?项目中的事务实现?脏读、不可重复读、幻读各举个例子?

1. 原子性(Atomicity)

      在一个事务内的操作,要么全部成功,要么全部失败。

2. 一致性(Consistency)

       数据库从一个一致性状态,转移到另一个一致性状态。

3. 隔离性(Isolation)

       多个并发的事务之间是相互隔离的

4.持久性(Durability)

       数据一旦被提交了,则改变就是永久的


事务隔离级别    脏读    不可重复读    幻读
读未提交(read-uncommitted)    是    是    是
不可重复读(read-committed)    否    是    是
可重复读(repeatable-read)    否    否    是
串行化(serializable)    否    否    否
 

 

Spring bean的生命周期?默认创建的模式是什么?不想单例怎么办?

实例化bean对象(通过构造方法或者工厂方法)
设置对象属性(setter等)(依赖注入)
如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。(和下面的一条均属于检查Aware接口)
如果Bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身
将Bean实例传递给Bean的后置处理器的postProcessBeforeInitialization(Object bean, String beanname)方法
调用Bean的初始化方法
将Bean实例传递给Bean的后置处理器的postProcessAfterInitialization(Object bean, String beanname)方法
使用Bean
容器关闭之前,调用Bean的销毁方法
默认创建的模式是什么

Spring框架中的Bean,或者说组件,获取实例的时候都是默认单例模式,这是在多线程开发的时候需要尤其注意的地方。

  单例模式的意思是只有一个实例,例如在Spring容器中某一个类只有一个实例,而且自行实例化后并项整个系统提供这个实例,这个类称为单例类。

  当多个用户同时请求一个服务时,容器会给每一个请求分配一个线程,这时多个线程会并发执行该请求对应的业务逻辑(成员方法),此时就要注意了,如果该处理逻辑中有对单例状态的修改(体现为该单例的成员属性),则必须考虑线程同步问题。


设计模式,单例模式,怎么保证线程安全?锁效率太低,怎么提高效率?CAS?CAS本质是什么?什么是原子性?Compare and Swap两步操作,为什么能保证原子性(涉及到CPU指令)?分布式锁?

还有什么设计模式?工厂模式有几种,都讲讲?简单工厂模式和工厂方法有什么差别?

 

数据库表怎么设计的?数据库范式?设计的过程中需要注意什么?enum类型的值一般怎么存?如果有一个十几位的小数为了不丢失精度怎么存?tinyint几个字节,int几个字节?

第一范式(1NF):强调的是列的原子性,即列不能够再分成其他几列。 

第二范式(2NF):首先是 1NF,另外包含两部分内容,一是表必须有一个主键;二是没有包含在主键中的列必须完全依赖于主键,而不能只依赖于主键的一部分。 

 第三范式(3NF):首先是 2NF,另外非主键列必须直接依赖于主键,不能存在传递依赖。即不能存在:非主键列 A 依赖于非主键列 B,非主键列 B 依赖于主键的情况。

 

 

面试

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值