阿里面试准备

1、自我介绍

2、项目介绍

3、Http协议

超文本传输协议,服务器传输超文本到本地浏览器的传送协议。

HTTP是一个基于TCP/IP通信协议来传递数据

HTTP协议工作于客户端-服务端架构为上。浏览器作为HTTP客户端通过URL向 HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后,向客户端发送响应信息。

Tcp和udp区别

TCP的优点: 可靠,稳定 TCP的可靠体现在TCP在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接用来节约系统资源。 TCP的缺点: 慢,效率低,占用系统资源高,易被攻击 TCP在传递数据之前,要先建连接,这会消耗时间,而且在数据传递时,确认机制、重传机制、拥塞控制机制等都会消耗大量的时间,而且要在每台设备上维护所有的传输连接,事实上,每个连接都会占用系统的CPU、内存等硬件资源。 而且,因为TCP有确认机制、三次握手机制,这些也导致TCP容易被人利用,实现DOS、DDOS、CC等攻击。

UDP的优点: 快,比TCP稍安全 UDP没有TCP的握手、确认、窗口、重传、拥塞控制等机制,UDP是一个无状态的传输协议,所以它在传递数据时非常快。没有TCP的这些机制,UDP较TCP被攻击者利用的漏洞就要少一些。但UDP也是无法避免攻击的,比如:UDP Flood攻击…… UDP的缺点: 不可靠,不稳定 因为UDP没有TCP那些可靠的机制,在数据传递时,如果网络质量不好,就会很容易丢包。 基于上面的优缺点,那么: 什么时候应该使用TCP: 当对网络通讯质量有要求的时候,比如:整个数据要准确无误的传递给对方,这往往用于一些要求可靠的应用,比如HTTP、HTTPS、FTP等传输文件的协议,POP、SMTP等邮件传输的协议。 在日常生活中,常见使用TCP协议的应用如下: 浏览器,用的HTTP FlashFXP,用的FTP Outlook,用的POP、SMTP Putty,用的Telnet、SSH QQ文件传输 ………… 什么时候应该使用UDP: 当对网络通讯质量要求不高的时候,要求网络通讯速度能尽量的快,这时就可以使用UDP。 比如,日常生活中,常见使用UDP协议的应用如下: QQ语音 QQ视频 TFTP ……

小结TCP与UDP的区别:

1.基于连接与无连接;
2.对系统资源的要求(TCP较多,UDP少);
3.UDP程序结构较简单;
4.流模式与数据报模式 ;

5.TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。

TCP与UDP区别总结:

1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接

2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付

3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的

UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)
4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信

5、TCP首部开销20字节;UDP的首部开销小,只有8个字节

6、TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

 

 

HTTP之状态码

状态代码有三位数字组成,第一个数字定义了响应的类别,共分五种类别:

1xx:指示信息--表示请求已接收,继续处理

2xx:成功--表示请求已被成功接收、理解、接受

3xx:重定向--要完成请求必须进行更进一步的操作

4xx:客户端错误--请求有语法错误或请求无法实现

5xx:服务器端错误--服务器未能实现合法的请求

 

  1. hashmap和concurrenthashmap区别及两者的优缺点

Hashtable和HashMap有几个主要的不同:线程安全以及速度。仅在你需要完全的线程安全的时候使用Hashtable,而如果你使用Java 5或以上的话,请使用ConcurrentHashMap吧。

下面直接来干货,先说这三个Map的区别:

HashTable

  • 底层数组+链表实现,无论key还是value都不能为null,线程安全,实现线程安全的方式是在修改数据时锁住整个HashTable,效率低,ConcurrentHashMap做了相关优化
  • 初始size为11,扩容:newsize = olesize*2+1
  • 计算index的方法:index = (hash & 0x7FFFFFFF) % tab.length

HashMap

  • 底层数组+链表实现,可以存储null键和null值,线程不安全
  • 初始size为16,扩容:newsize = oldsize*2,size一定为2的n次幂
  • 扩容针对整个Map,每次扩容时,原来数组中的元素依次重新计算存放位置,并重新插入
  • 插入元素后才判断该不该扩容,有可能无效扩容(插入后如果扩容,如果没有再次插入,就会产生无效扩容)
  • 当Map中元素总数超过Entry数组的75%,触发扩容操作,为了减少链表长度,元素分配更均匀
  • 计算index方法:index = hash & (tab.length – 1)

 

HashMap的初始值还要考虑加载因子:

  •  哈希冲突:若干Key的哈希值按数组大小取模后,如果落在同一个数组下标上,将组成一条Entry链,对Key的查找需要遍历Entry链上的每个元素执行equals()比较。
  • 加载因子:为了降低哈希冲突的概率,默认当HashMap中的键值对达到数组大小的75%时,即会触发扩容。因此,如果预估容量是100,即需要设定100/0.75=134的数组大小。
  • 空间换时间:如果希望加快Key查找的时间,还可以进一步降低加载因子,加大初始大小,以降低哈希冲突的概率。

HashMap和Hashtable都是用hash算法来决定其元素的存储,因此HashMap和Hashtable的hash表包含如下属性:

  • 容量(capacity):hash表中桶的数量
  • 初始化容量(initial capacity):创建hash表时桶的数量,HashMap允许在构造器中指定初始化容量
  • 尺寸(size):当前hash表中记录的数量
  • 负载因子(load factor):负载因子等于“size/capacity”。负载因子为0,表示空的hash表,0.5表示半满的散列表,依此类推。轻负载的散列表具有冲突少、适宜插入与查询的特点(但是使用Iterator迭代元素时比较慢)

除此之外,hash表里还有一个“负载极限”,“负载极限”是一个0~1的数值,“负载极限”决定了hash表的最大填满程度。当hash表中的负载因子达到指定的“负载极限”时,hash表会自动成倍地增加容量(桶的数量),并将原有的对象重新分配,放入新的桶内,这称为rehashing。

HashMap和Hashtable的构造器允许指定一个负载极限,HashMap和Hashtable默认的“负载极限”为0.75,这表明当该hash表的3/4已经被填满时,hash表会发生rehashing。

“负载极限”的默认值(0.75)是时间和空间成本上的一种折中:

  • 较高的“负载极限”可以降低hash表所占用的内存空间,但会增加查询数据的时间开销,而查询是最频繁的操作(HashMap的get()与put()方法都要用到查询)
  • 较低的“负载极限”会提高查询数据的性能,但会增加hash表所占用的内存开销

程序猿可以根据实际情况来调整“负载极限”值。

ConcurrentHashMap

  • 底层采用分段的数组+链表实现,线程安全
  • 通过把整个Map分为N个Segment,可以提供相同的线程安全,但是效率提升N倍,默认提升16倍。(读操作不加锁,由于HashEntry的value变量是 volatile的,也能保证读取到最新的值。)
  • Hashtable的synchronized是针对整张Hash表的,即每次锁住整张表让线程独占,ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术
  • 有些方法需要跨段,比如size()和containsValue(),它们可能需要锁定整个表而而不仅仅是某个段,这需要按顺序锁定所有段,操作完毕后,又按顺序释放所有段的锁
  • 扩容:段内扩容(段内元素超过该段对应Entry数组长度的75%触发扩容,不会对整个Map进行扩容),插入前检测需不需要扩容,有效避免无效扩容

Hashtable和HashMap都实现了Map接口,但是Hashtable的实现是基于Dictionary抽象类的。Java5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。

HashMap基于哈希思想,实现对数据的读写。当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,然后找到bucket位置来存储值对象。当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。HashMap使用链表来解决碰撞问题,当发生碰撞时,对象将会储存在链表的下一个节点中。HashMap在每个链表节点中储存键值对对象。当两个不同的键对象的hashcode相同时,它们会储存在同一个bucket位置的链表中,可通过键对象的equals()方法来找到键值对。如果链表大小超过阈值(TREEIFY_THRESHOLD,8),链表就会被改造为树形结构。

在HashMap中,null可以作为键,这样的键只有一个,但可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示HashMap中没有该key,也可以表示该key所对应的value为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个key,应该用containsKey()方法来判断。而在Hashtable中,无论是key还是value都不能为null。

Hashtable是线程安全的,它的方法是同步的,可以直接用在多线程环境中。而HashMap则不是线程安全的,在多线程环境中,需要手动实现同步机制。

Hashtable与HashMap另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。

从类图中可以看出来在存储结构中ConcurrentHashMap比HashMap多出了一个类Segment,而Segment是一个可重入锁。

ConcurrentHashMap是使用了锁分段技术来保证线程安全的。

锁分段技术:首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。 

ConcurrentHashMap提供了与Hashtable和SynchronizedMap不同的锁机制。Hashtable中采用的锁机制是一次锁住整个hash表,从而在同一时刻只能由一个线程对其进行操作;而ConcurrentHashMap中则是一次锁住一个桶。

ConcurrentHashMap默认将hash表分为16个桶,诸如get、put、remove等常用操作只锁住当前需要用到的桶。这样,原来只能一个线程进入,现在却能同时有16个写线程执行,并发性能的提升是显而易见的。


ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成。Segment是一个可重入锁(ReentrantLock),在ConcurrentHashMap里扮演锁的角色;HashEntry则用于存储键值对数据。一个ConcurrentHashMap里包含一个Segment数组。Segment的结构和HashMap类似,是一种数组和链表结构。一个Segment里包含一个HashEntry数组,每个HashEntry是一个链表结构的元素,每个Segment守护着一个HashEntry数组里的元素。当对HashEntry数组的数据进行修改时,必须首先获得与它对应的segment锁。
你说的一次锁住一个桶即segment,然而一个Segment里包含一个HashEntry数组。

 

 

  1. 对MySQL的了解,和oracle的区别

(1) 对事务的提交
    MySQL默认是自动提交,而Oracle默认不自动提交,需要用户手动提交,需要在写commit;指令或者点击commit按钮
(2) 分页查询
    MySQL是直接在SQL语句中写"select... from ...where...limit  x, y",有limit就可以实现分页;而Oracle则是需要用到伪列ROWNUM和嵌套查询
(3) 事务隔离级别
      MySQL是read commited的隔离级别,而Oracle是repeatable read的隔离级别,同时二者都支持serializable串行化事务隔离级别,可以实现最高级别的
    读一致性。每个session提交后其他session才能看到提交的更改。Oracle通过在undo表空间中构造多版本数据块来实现读一致性,每个session
    查询时,如果对应的数据块发生变化,Oracle会在undo表空间中为这个session构造它查询时的旧的数据块
    MySQL没有类似Oracle的构造多版本数据块的机制,只支持read commited的隔离级别。一个session读取数据时,其他session不能更改数据,但
    可以在表最后插入数据。session更新数据时,要加上排它锁,其他session无法访问数据
(4) 对事务的支持
    MySQL在innodb存储引擎的行级锁的情况下才可支持事务,而Oracle则完全支持事务
(5) 保存数据的持久性
    MySQL是在数据库更新或者重启,则会丢失数据,Oracle把提交的sql操作线写入了在线联机日志文件中,保持到了磁盘上,可以随时恢复
(6) 并发性
    MySQL以表级锁为主,对资源锁定的粒度很大,如果一个session对一个表加锁时间过长,会让其他session无法更新此表中的数据。
  虽然InnoDB引擎的表可以用行级锁,但这个行级锁的机制依赖于表的索引,如果表没有索引,或者sql语句没有使用索引,那么仍然使用表级锁。
  Oracle使用行级锁,对资源锁定的粒度要小很多,只是锁定sql需要的资源,并且加锁是在数据库中的数据行上,不依赖与索引。所以Oracle对并
  发性的支持要好很多。
(7) 逻辑备份
    MySQL逻辑备份时要锁定数据,才能保证备份的数据是一致的,影响业务正常的dml使用,Oracle逻辑备份时不锁定数据,且备份的数据是一致
(8) 复制
    MySQL:复制服务器配置简单,但主库出问题时,丛库有可能丢失一定的数据。且需要手工切换丛库到主库。
    Oracle:既有推或拉式的传统数据复制,也有dataguard的双机或多机容灾机制,主库出现问题是,可以自动切换备库到主库,但配置管理较复杂。
(9) 性能诊断
    MySQL的诊断调优方法较少,主要有查询日志。
    Oracle有各种成熟的性能诊断调优工具,能实现很多自动分析、诊断功能。比如awr、addm、sqltrace、tkproof等    
(10)权限与安全
    MySQL的用户与主机有关,感觉没有什么意义,另外更容易被仿冒主机及ip有可乘之机。
    Oracle的权限与安全概念比较传统,中规中矩。
(11)分区表和分区索引
    MySQL的分区表还不太成熟稳定。
    Oracle的分区表和分区索引功能很成熟,可以提高用户访问db的体验。
(12)管理工具
    MySQL管理工具较少,在linux下的管理工具的安装有时要安装额外的包(phpmyadmin, etc),有一定复杂性。
    Oracle有多种成熟的命令行、图形界面、web管理工具,还有很多第三方的管理工具,管理极其方便高效。
(13)最重要的区别
    MySQL是轻量型数据库,并且免费,没有服务恢复数据。
    Oracle是重量型数据库,收费,Oracle公司对Oracle数据库有任何服务。

4、对设计模式的看法和认知

设计模式就是把生活中的例子归纳总结放到程序里来,是一种思想,代码只是表现形式,不止是设计模式,程序中的绝大多数都是来源于生活,并高于生活。(NIO)

1. 它们记录了专家的经验,并且让非专家也能理解。

2. 它们的名称构成了一份词汇表,帮助开发者更好的交流。

3. 它们帮助人们更快的理解一个系统,只要这个系统是用模式的方式描述的。

4. 它们使系统的重组变得更容易,不管原来的系统是否以模式的方式设计的。

 

1、有哪些设计模式

工厂模式(Factory) 只对结果负责,不要三无产品。

单例模式(Singleton) 保证独一无二。

适配器模式(Adapter) 需要一个转换头(兼容)。

装饰器模式(Decorator) 需要包装,但不改变本质(同宗同源)。

代理模式(Proxy) 办事要求人,所以找代理。

观察者模式(Observer) 完成时通知我。

策略模式(Strategy) 我行我素,达到目的就行。

模板模式(Template) 流程标准化,原料自己加。

委派模式(Delegate) 干活是你的(普通员工),功劳是我的(项目经理)。

原型模式(Prototype) 拔一根猴毛,吹出千万个。

2、设计模式的六大原则

总原则:开闭原则

1、单一职责原则

2、里氏替换原则

3、依赖倒转原则

4、接口隔离原则

5、迪米特法则(最少知道原则)

6、合成复用原则

 

 

1、Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的 存储。
2 Redis支持数据的备份,即master-slave模式的数据备份。
3 Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次 加载进行使用。

6、多线程如何避免死锁

死锁的产生,资源的抢夺竞争,进程推进顺序非法,

  1. 加锁顺序(线程按照一定的顺序加锁)
  2. 加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁)
  3. 死锁检测

 

对Runtime的了解

7、模块化的好处

Java模块,就是插件plugins['plʌgɪn]实现。任何系统都可以拆分成模块

1、功能模块化、分开编写,互不干涉,开发效率

2、代码模块,实现解耦。分层分块,复用

8、hashmap、LinkedHashMap、TreeMap

1、 HashMap中key的值没有顺序,常用来做统计。

 

2、LinkedHashMap吧。它内部有一个链表,保持Key插入的顺序。迭代的时候,也是按照插入顺序迭代,而且迭代比HashMap快。

 

3、TreeMap的顺序是Key的自然顺序(如整数从小到大),也可以指定比较函数。但不是插入的顺序。

9、Final关键字的特性

1表面意思就是不可更改的

2修饰位置不同,作用也不同

3修饰变量,值不可变。修饰对象,引用不可变但是对象值可变。修饰方法,方式不可重写。修饰类,类不可被继承

4使用final关键字,如果编译器能够在编译阶段确定某变量的值,那么编译器就会把该变量当做编译期常量来使用。如果需要在运行时确定,那么编译器就不会优化相关代码。

5 finalize()是Object中的方法,当垃圾回收器将要回收对象所占内存之前被调用,即当一个对象被虚拟机宣告死亡时会先调用它finalize()方法,让此对象处理它生前的最后事情(这个对象可以趁这个时机挣脱死亡的命运)。要明白这个问题,先看一下虚拟机是如何判断一个对象该死的。

6将类、方法、变量声明为final能够提高性能,这样JVM就有机会进行估计,然后优化。

7接口中的变量都是public static final 的

10、集合

Collection
List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
Set
Map
├Hashtable
├HashMap
└WeakHashMap

ArrayList是动态数组

Linkedlist是双向链表

Vector是动态数组(线程安全的)

Stack栈

Hashmap的实现

  1. hashmap是有链表和数组组成的
  2. 哈希算法对应地址,哈希值%容量得到数组位置,也就是bucket (桶)位置,entry对象里面<key,value>
  3. 哈希碰撞问题,hashcode,equals对比是重新赋值还是放入链表(更好哈希算法,减少碰撞问题,也就效率提高,链表查找效率低下)
  4. 如果哈希值相同,找到bucket位置之后,会调用keys.equals()方法去找到链表中正确的节点,最终找到要找的值对象
  5. 重新调整大小  赋值因子 3/4,多线程不安全,发生竞争

Hashmap和hashtable的区别

  1. 线程安全问题,这就是操作快慢
  2. 不能为空,hashmap可以空键和值

 

Hashmap和concurrenthashmap的区别

1、线程安全,重入锁,分段数组segment

2、不能为空,hashmap可以空键和值

11、Jvm虚拟机的内存结构,每个结构是干嘛的

栈 是处理逻辑,程序自己分配空间。线程私有。一个方法以这个栈帧,例子死循环

堆 是具体数据,

方法区 类加载信息,静态变量,方法,常量,全局变量

程序计算器 线程独享,程序走到那个位置

 

12、GC什么时候触发,算法有哪些,优缺点是什么,垃圾回收器的选择,优化方案是什么

gc触发是1、人工调用回收,system.gc()  2、系统自身决定gc

Gc是怎么判断对象可以回收的 是在引用计数或者可达性。

Minor GC ,Full GC 触发条件

Minor GC触发条件:当Eden区满时,触发Minor GC。

 

Full GC触发条件:

(1)调用System.gc时,系统建议执行Full GC,但是不必然执行

(2)老年代空间不足

(3)方法区空间不足

(4)通过Minor GC后进入老年代的平均大小大于老年代的可用内存

(5)由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小

算法有哪些

标记清除算法,标记整理算法,复制回收算法,标记整理算法,分代收集

 

 

回收器是回收算法的实现

回收器的选择

Serial minorGC, serialOld majorGC串行回收,单线程

parnew  minorGC 单,再多线程

parallel scavenger(并行回收)minorGC   parallelOld  majorGC

Cms  majorGC并发标记清除收集器,初始标记--并发标记--重新标记--并发清除

G1收集器 minorGC 、majorGC. Garbage First Collector,初始标记--并发标记--最终标记--筛选回

监控工具:jvm参数命令行日志输出,MAT,JVisualVM

13、Jvm调优

就是要避免fullGC和gc频率,还有每次gc时间。达到最终gc总时间小,程序停顿小

1、堆大小的调优

一般来说调整参数,越大越好,1、降低gc频率但也会增加单次gc的时间2、对象更有可能成为垃圾

小心平衡调整new和old的比例。可以把Xms/Xmx调整为一样大,初始一般为内存的1/64,1/4。避免频繁调整,每次调整都会触发一次FullGC.当然也不总是,1、堆调整代价大但是如果死机了呢。还不如一次fullgc

2、新生代调优

1、Eden区大小调整,xmn,降低gc频率

2、晋升,(1)尽可能让对象待在survival中,使之在新生代被收回,不然进入old区,降低旧生代的对象和gc。(2)调整比例,平衡点。New 里面的Eden和survival0. survival01  8:1:1。(3)新生代长时间没被回收的,设置阀值,进行放入Old,避免频繁copy

3、旧生代的调优

1、尽可能对新生代调优,在不紧要的时候受用fullgc。加Cpu,硬件调整。

2、程序优化

 

14、NIO设计思想

BIO和NIO区别

都是同步的,区别就是阻塞和非阻塞

阻塞和非阻塞

区别就是阻塞需要等待,一个线程同时只能做一件事,依赖于需要等待的资源,非阻塞不需要,先进来,排号,二次轮询机制,有没有在排号,有则轮询set  <seletekeys>,取出来,移除队列,在处理,线程可控。因为缓冲区存在,可以实现读写分离和同时读写,不需要等待,边写边读数据。Buffer

 

同步和异步

多路复用和selector、buffer

15、concurrent包

BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题。

BlockingQueue不光实现了一个完整队列所具有的基本功能,同时在多线程环境下,他还自动管理了多线间的自动等待和唤醒功能,从而使得程序员可以忽略这些细节,关注更高级的功能。 

CyclicBarrier栅栏,await

以前是wait notify,synchronize做并发

ConcurrentHashMap 
多线程的时候可以完全替换hashmap和hashtable了,这玩意是按段加锁的,读写快、线程安全,性能完爆hashtable。
ConcurrentNavigableMap

加强版的,主要是获取子map非常方便,headMap、tailMap、submap。
CountDownLatch

锁,初始化一个数字,countDown一次减去一个,期间调用await()就会阻塞,直到0才会释放。
CyclicBarrier

所有的线程汇合才会继续执行,当然,你也可以设置超时时间。

17、mysql

1、mysql的三大引擎是啥?

CAID,一致性,隔离性,持久性

 

mysql常用的引擎有InnoDB,MyISAM,Memory,默认是InnoDB

InnoDB:磁盘表,支持事务,支持行级锁,B+Tree索引

ps:优点: 具有良好的ACID特性。适用于高并发,更新操作比较多的表。需要使用事务的表。对自动灾难恢复有要求的表。

缺点:读写效率相对MYISAM比较差。占用的磁盘空间比较大。

mysql的4大特性+4种隔离级别:

MyISAM:磁盘表,不支持事务,支持表级锁,B+Tree索引

ps: 优点:占用空间小,处理速度快(相对InnoDB来说)

缺点:不支持事务的完整性和并发性

MEMORY(Heap):内存表,不支持事务,表级锁,Hash索引,不支持Blob,Text大类型

ps: 优点:速度要求快的,临时数据

缺点:丢失以后,对项目整体没有或者负面影响不大的时候。

2redis的hash算法用的是啥?

redis应该是使用一致性hash算法---MurmurHash3 算法,具有低碰撞率优点,google改进的版本cityhash也是redis中用到的哈希算法。

现有的主流的大数据系统都是用的 MurmurHash本身或者改进

  1. Nosql是非关系型数据库,因为不需要满足关系数据库数据一致性等复杂特性所以速度快;

18、CPU占用过高

一般是死循环,比如日志文件过大,磁盘占满了,输出日志线程死循环。删除日志文件解决

19、jdk的几种线程池

  1. 固定线程数的线程池(newFixedThreadPool)

线程数为Cpu核数*N, FixedThreadPool 是通过 java.util.concurrent.Executors 创建的 ThreadPoolExecutor 实例。这个实例会复用 固定数量的线程处理一个共享的无边界队列 。任何时间点,最多有 nThreads 个线程会处于活动状态执行任务。如果当所有线程都是活动时,有多的任务被提交过来,那么它会一致在队列中等待直到有线程可用。如果任何线程在执行过程中因为错误而中止,新的线程会替代它的位置来执行后续的任务。所有线程都会一致存于线程池中,直到显式的执行 ExecutorService.shutdown() 关闭。由于阻塞队列使用了LinkedBlockingQueue,是一个无界队列,因此永远不可能拒绝任务。LinkedBlockingQueue在入队列和出队列时使用的是不同的Lock,意味着他们之间不存在互斥关系,在多CPU情况下,他们能正在在同一时刻既消费,又生产,真正做到并行。因此这种线程池不会拒绝任务,而且不会开辟新的线程,也不会因为线程的长时间不使用而销毁线程。这是典型的生产者----消费者问题,这种线程池适合用在稳定且固定的并发场景,比如服务器。下面代码给出一个固定线程数的DEMO,每个核绑定了5个线程。

  1. 缓存的线程池 (newCacheThreadPool)

初始为0,最大线程数为最大整型的长度。这意味着所有的任务一提交就会加入到阻塞队列中。当线程池中的线程60s没有执行任务就终止,阻塞队列为SynchronousQueue。SynchronousQueue的take操作需要put操作等待,put操作需要take操作等待,否则会阻塞(线程池的阻塞队列不能存储,所以当目前线程处理忙碌状态时,所以开辟新的线程来处理请求),线程进入wait set。总结下来:①这是一个可以无限扩大的线程池;②适合处理执行时间比较小的任务;③线程空闲时间超过60s就会被杀死,所以长时间处于空闲状态的时候,这种线程池几乎不占用资源;④阻塞队列没有存储空间,只要请求到来,就必须找到一条空闲线程去处理这个请求,找不到则在线程池新开辟一条线程。如果主线程提交任务的速度远远大于CachedThreadPool的处理速度,则CachedThreadPool会不断地创建新线程来执行任务,这样有可能会导致系统耗尽CPU和内存资源,所以在使用该线程池是,一定要注意控制并发的任务数,否则创建大量的线程可能导致严重的性能问题。

  1. 单个线程的线程池(singleThreadPoolExecutor)

SingleThreadExecutor是使用单个worker线程的Executor,作为单一worker线程的线程池,SingleThreadExecutor把corePool和maximumPoolSize均被设置为1,和FixedThreadPool一样使用的是无界队列LinkedBlockingQueue,所以带来的影响和FixedThreadPool一样。对于newSingleThreadExecutor()来说,也是当线程运行时抛出异常的时候会有新的线程加入线程池替他完成接下来的任务。创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行,所以这个比较适合那些需要按序执行任务的场景。比如:一些不太重要的收尾,日志等工作可以放到单线程的线程中去执行。日志记录一般情况会比较慢(数据量大一般可能不写入数据库),顺序执行会拖慢整个接口,堆积更多请求,还可能会对数据库造成影响(事务在开启中),所以日志记录完全可以扔到单线程的线程中去,一条条的处理,也可以认为是一个单消费者的生产者消费者模式。

4、固定个数的线程池(NewScheduledTreadPool)

相比第一个,可以执行延时任务和带返回值的任务

20、sql优化有哪些

  1. 建立索引
  2. Sql本身优化,不用*,少用like和函数,不用嵌套语句,查询顺序
  3. 大表拆小表   横向(把字段拆分)和纵向(分库分表)以id段或者日期,靠代码可以关联
  4. 加冗余字段
  5. 什么时候可以加冗余字段?什么情况下不可以加呢?
  6. 如果这个冗余字段的数据经常改变,就不建议加冗余字段了
  7. 不创建外键,靠代码和sql控制
  8. 读写分离
  9. 数据库参数调优(专业DBA处理)
  10. 服务器优化(专业运维或项目经理处理)

 

常见优化Sql查询性能的方法有哪些?

1、查询条件减少使用函数,避免全表扫描

2、减少不必要的表连接

3、有些数据操作的业务逻辑可以放到应用层进行实现

3、可以使用with as

4、使用“临时表”暂存中间结果

5、不要把SQL语句写得太复杂

6、不能循环执行查询

7、用 exists 代替 in 

8、表关联关系不要太纠结

9、查询多用索引列取查,用charindex或者like[0-9]来代替%%

10、inner关联的表可以先查出来,再去关联leftjoin的表

11、可以进行表关联数据拆分,即先查出核心数据,再通过核心数据查其他数据,这样会快得多

12、参考SQL执行顺序进行优化

13、表关联时取别名,也能提高效率

14、使用视图,给视图建立索引进行优化

15、使用数据仓库的形式,建立单独的表存储数据,根据时间戳定期更新数据。将多表关联的数据集中抽取存入一张表中,查询时单表查询,提高了查询效率。

28、sleep和wait

对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。

sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。

在调用sleep()方法的过程中,线程不会释放对象锁。

而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备

获取对象锁进入运行状态

21、TCP 和 UDP 的区别?TCP 数据传输过程中怎么做到可靠的?

什么是可靠,所谓的可靠就是说发送方发送的数据到达接收方的时候不会发生错误,不会丢失,不会乱序

Tcp  可靠稳定的连接,拥有确认,滑动窗口(校验)重传,拥塞,传输完成会断开连接。慢,效率低,占用资源高。会被攻击,报文,一对一

Udp  无连接,对完整性,通讯质量要求不高,网络速度要求高。比如语音,视频,流,多对多

22、排序算法

1、冒泡算法 O(n2)

for(int i=0;i<n;i++){

For(int j=0;j<n-1-i;j++){

}}

2、

选择O(n2)  不稳定

快速O(n2)

插入

归并

5、如何实现分布式缓存

Redis、memecache区别

23、微服务

  1. 核心就是服务发现和负载均衡。代理proxy来解决问题
  2. Springclound+Consul>eurke>dubbo+zookeeper协调

24、注册中心有哪些

Springcloud的eureka   ap   可用性Availability

Dubbo的zk cp 一致性consistant

Consul  cp

16、spring的IOC用到了java中的那些特性

控制反转->DI依赖注入->反射

25、spring和springboot区别

  1. Spring Boot是一套遵循的约定大于配置的体系
  2. 几乎无配置,内置启动容器

26、反射的机制

一、反射机制的概念:

指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能调用它的任意一个方法.这种动态获取信息,以及动态调用对象方法的功能叫java语言的反射机制.

二 、 反射机制的应用:

生成动态代理,面向切片编程(在调用方法的前后各加栈帧).

 

27、object的方法

Hashcode(),tostring(),equals()

重写Hashcode重写,equals必须重写

hashCode()用来定位要存放的位置,equals()用来判断是否相等。 

equals被用来判断两个对象是否相等。

equals通常用来比较两个对象的内容是否相等,==用来比较两个对象的地址是否相等。

29、cas操作,compare and swap 比较和替换

用synchronize或者atomic

30、类加载器种类

启动类加载器:Bootstrap ClassLoader,加载JACA_HOME\lib,或者被 -Xbootclasspath参数限定的类


扩展类加载器,Extension ClassLoader,加载\lib\ext,或者被java.ext.dirs系统变 量指定的类


应用程序类加载器,Application ClassLoader,加载ClassPath中的类库


自定义类加载器,通过继承ClassLoader实现,一般是加载我们的自定义类

 

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值