我的知识点

数组 :数据存储区间是连续的,占用内存严重,空间复杂度大。数组的二分查找时间复杂度比较小。数组特点:查询容易,插入和删除困难
链表: 链表存储区间离散,占用内存比较宽松,空间复杂度小,但是时间复杂度大。链表特点:查询困难,插入和删除容易。

1.HashMap的源码,实现原理,JDK8中对HashMap做了怎样的优化?

哈希表是由数组和链表组成的,一个长度为16的数组中,每个元素存储的是一个链表的头结点。元素是按照hash(key)%len,也就是元素的key的哈希值对数组长度取模得到。hashMap存储数据的容器就是一个线性数组,hashmap里面实现了一个静态内部类Entry,其重要的属性有key,value,next。entry是hashMap的一个基础bean,map里面的数据都存储在Entry[]里面。

2.hashMap的扩容机制?

当向容器添加元素的时候,会判断当前容器的元素个数,如果大于等于阀值–当前数组的长度乘以加载因子的值时候,就要自动扩容。
java数组是无法自动扩容的,数组扩容是用一个新的数组代替已有容量小的数组。

hashmap扩容会将长度扩容到之前的2倍。

  1. hashMap,hashTable,ConsurrentHashMap三者的区别?

HashMap没有同步考虑,hashTable使用了Synchornized。单线程使用hashMap提高效率,多线程使用hashTable保证安全。
HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。
HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。
HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。
Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。
最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。
Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。

ConcurrentHashMap将hash表分为16个桶(默认值),诸如get,put,remove等常用操作只锁当前需要用到的桶。试想,原来只能一个线程进入,现在却能同时16个写线程进入(写线程才需要锁定,而读线程几乎不受限制,之后会提到),并发性的提升是显而易见的。
更令人惊讶的是ConcurrentHashMap的读取并发,因为在读取的大多数时候都没有用到锁定,所以读取操作几乎是完全的并发操作,而写操作锁定的粒度又非常细,比起之前又更加快速(这一点在桶更多时表现得更明显些)。只有在求size等操作时才需要锁定整个表。而在迭代时,ConcurrentHashMap使用了不同于传统集合的快速失败迭代器(见之前的文章《JAVA API备忘—集合》)的另一种迭代方式,我们称为弱一致迭代器。在这种迭代方式中,当iterator被创建后集合再发生改变就不再是抛出ConcurrentModificationException,取而代之的是在改变时new新的数据从而不影响原有的数据,iterator完成后再将头指针替换为新的数据,这样iterator线程可以使用原来老的数据,而写线程也可以并发的完成改变,更重要的,这保证了多个线程并发执行的连续性和扩展性,是性能提升的关键。
4. java 4中权限修饰符的作用范围。

public 修饰的成员,在同类,同包,子类,其他包中都可以访问

protected 修饰的成员,在同类,同包,子类中可以访问,但是在其他包下不可以访问。

default 修饰的成员,在同类,同包中可以访问,但是在其他包中不管是不是子类都不能访问

private修饰的成员,只能在同类中被访问。‘

public 和default都可以修饰类和成员变量,而protected和private都不可以修饰类。

5 . object类中的方法?

5.1 toString()
5.2 equals()    
5.3 hashCode()
5.4 notify()
5.5 notifyAll()
5.6 getClass()
5.7 wait()

6 .接口和抽象类的区别,注意JDK8的接口可以有实现?

    6.1 接口可以多实现,抽象类只能单独被继承,
    6.2 抽象类必须加abstract修饰,接口默认是public abstract
    6.3 抽象类可以有构造方法,接口不能含有构造方法

7 . java实现动态代理的两种方式:

    7.1 JDK动态代理
    7.2 cglib产生代理

这两种方法各有好坏。jdk动态代理是由java内部的反射机制生成字节码并生成对象来实现的,而cglib代理底层是借助asm来实现的,这个asm就是一个java字节码操纵框架,它能用来动态生成类或者增强类的功能,ASM从类文件中读入信息后,改变类的行为,分析类的信息,这就跟aop实现方式中的静态织入的是一样的,就是相当于把切面织入类的字节码文件中,以此达到拦截的作用。一般jdk动态代理用于目标类都是基于统一的接口,cglib多用于对类的代理,这些类不需要实现统一的接口。

  1. 传值和传引用的区别,Java是怎么样的,有没有传值引用?

    java所有操作都是传值操作。 
    

    值传递:方法调用时,实际参数把它的值的副本传递给对应的形式参数。特点:此时内存中存在两个相等的基本类型,即实际参数和形式参数,后面方法中的操作都是对形参这个值的修改,不影响实际参数的值。

  2. 一个ArrayList在循环过程中删除,会不会出问题,为什么?

    list 有序,可重复。遍历删除,arraylist的长度就变化了, 会出现数组下标越界。使用迭代器iterator()。

10 . @transactional注解在什么情况下会失效,为什么?

    编译时异常不会回滚(超时,网络异常,文件肚子饿),运行时异常会回滚(空指针,数组下标越界,1/0)。

11 . b+树

 每个节点有多个child,一颗b+树包含根节点,内部节点,叶子结点。根节点可能是一个叶子节点,也可能是一个包含两个或两个以上的孩子节点的节点。
 B+树通常用于数据库和操作系统的文件系统中,能够保持数据稳定有序,插入和修改拥有较稳定的对数时间复杂度,B+树自底向上插入。

12 . 一致性hash算法

一致性hash作为一个负载均衡算法,可以用在分布式缓存、数据库的分库分表等场景中,还可以应用在负载均衡器中作为作为负载均衡算法。在有多台服务器时,对于某个请求资源通过hash算法,映射到某一个台服务器,当增加或减少一台服务器时,可能会改变这些资源对应的hash值,这样可能导致一部分缓存或数据失效了。一致性hash就是尽可能在将同一个资源请求路由到同一台服务器中。
普通hash,当我们增加一个节点的时候,所有数据都要重新迁移。一致性hash,首先把2的32次方抽象成一个环。比如说集群有四个节点,他们会根据hash后映射到环上的某个点,在存储数据的时候这些点按照顺时针方向,找到距离自己最近的一个物理节点就是要存储的节点。当增加一个节点的时候,只会影响这个节点前后两个节点之间的数据,其他数据不受影响。如果出现负载不均衡的情况,增加虚拟节点,然后把这些虚拟节点映射到物理节点。

13 . jvm的内存结构

JVM内存结构主要有三大块:堆内存、方法区和栈。
堆内存是JVM中最大的一块由年轻代和老年代组成,new创建的实例化对象及数组,是存放在堆内存中的,用完之后靠垃圾回收机制不定期自动消除。
方法区存储类信息、常量、静态变量等数据,是线程共享的区域,
栈又分为java虚拟机栈和本地方法栈主要用于方法的执行。基本数据类型、局部变量都是存放在栈内存中的,用完就消失。

14 . Java类加载的过程?

    14.1 加载  获取类的二进制字节流,将这个字节流所代表的静态存储结构转化为方法区的运行

时结构,在java堆中生成一个代表这个类的java.lang.Class对象>,作为方法区的数据访问入口。
14.2 验证 验证class独享的字节流包含的信息是否符合jvm要求,不会危害jvm的安全
14.3 准备 类变量分配内存并设置类变量的初始值
14.4 解析 虚拟机将常量池的符号引用替换为直接引用的过程
14.5 初始化 执行类中定义的java代码
15 . JVM调优,常用JVM参数配置

    15.1 打开GC各种日志(每次执行GC信息都能打印,获得执行时间,空间大小)
    15.2 类加载监控:(监控类加载的顺序)
    15.3 堆的分配参数
    15.4 栈的分配参数

16 . Java实现多线程有哪几种方式?

16.1 继承Thread类实现多线程
16.2 实现Runnable接口方式实现多线程
16.3 使用ExecutorService、Callable、Future实现有返回结果的多线程

java1.5 引入的有返回有返回结果的线程,前两个的缺点就是没有返回结果。

17 . 线程池的参数有哪些,在线程池创建一个线程的过程?

 corePoolSize : 核心池的大小
 maximumPoolSize : 线程池的最大线程数
 keepAliveTime : 表示线程没有任务执行时最多保持多久时间会终止
 unit : 参数keepAliveTime的时间单位
 workQueue : 一个阻塞队列,用来存储等待执行的任务
 threadFactory:线程工厂,主要用来创建线程
 handler:表示当拒绝处理任务时的策略

18 . volitile关键字的作用,原理?

一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:
 1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
  2)禁止进行指令重排序。

原理涉及到java的内存模型。
19 . synchronized关键字的用法,优缺点?

jvm实现的一个锁机制。是一种同步锁。
synchronized是不错,但它并不完美。它有一些功能性的限制:
    --它无法中断一个正在等候获得锁的线程;
    -也无法通过投票得到锁,如果不想等下去,也就没法得到锁;
    --同步还要求锁的释放只能在与获得锁所在的堆栈帧相同的堆栈帧中进行,多数情况下,这没问题(而且与异常处理交互得很好),但是,确实存在一些非块结构的锁定更合适的情况

20 . 线程的状态?

新生状态
就绪状态
运行状态
阻塞状态
死亡状态

21 . sleep和wait的区别?

对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。
sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。在调用sleep()方法的过程中,线程不会释放对象锁。
而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备。

22 . notify和notifyall的区别?

notify只会通知一个在等待的对象,而notifyAll会通知所有在等待的对象,并且所有对象都会继续运行。

23 . ThreadLocal的了解,实现原理?

    总结:ThreadLocal不是为了解决多线程访问共享变量,而是为每个线程创建一个单独的变量副本,提供了保持对象的方法和避免参数传递的复杂性。
    ThreadLocal可以看做是一个容器,容器里面存放着属于当前线程的变量。ThreadLocal类提供了四个对外开放的接口方法,这也是用户操作ThreadLocal类的基本方法:
    (1) void set(Object value)设置当前线程的线程局部变量的值。 
    (2) public Object get()该方法返回当前线程所对应的线程局部变量。 
    (3) public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。  

24 . 常见的数据库优化手段

    24.1 减少数据访问(减少磁盘访问)
    24.2 返回更少的数据(减少网络传输或磁盘访问)
    24.3 减少交互次数(减少网络传输)
    24.4 减少cpu及内存开销()
    24.5 利用更多资源(增加资源)

25 . 索引的优缺点,什么字段上建立索引?

25.1 索引就像是书的目录,是与表或视图关联的磁盘上结构,可以加快从表或视图中检索行的速度。索引中包含由表或视图中的一列或多列生成的键。这些键存储在一个结构(BTree)中,使SQL可以快速有效地查找与键值关联的行。

25.2. 为什么要建立索引,即索引的优点:

    ①  建立索引的列可以保证行的唯一性,生成唯一的rowId

    ②  建立索引可以有效缩短数据的检索时间

    ③  建立索引可以加快表与表之间的连接

    ④  为用来排序或者是分组的字段添加索引可以加快分组和排序顺序

   25.3. 索引的缺点:

① 创建索引和维护索引需要时间成本,这个成本随着数据量的增加而加大

② 创建索引和维护索引需要空间成本,每一条索引都要占据数据库的物理存储空间,数据量越大,占用空间也越大(数据表占据的是数据库的数据空间)
③ 会降低表的增删改的效率,因为每次增删改索引需要进行动态维护,导致时间变长

    25.4. 什么样的表跟列要建立索引:
    ①  总的来说就是数据量大的,经常进行查询操作的表要建立索引
    ④  用于排序的字段可以添加索引,用于分组的字段应当视情况看是否需要添加索引。
    ⑤  添加多列索引的时候,对应的多条件查询可以触发该索引的同时,索引最左侧的列的单条件查询也可以触发。
    ⑥  如果有些表注定只会进行查询所有,也就没必要添加索引,因为查询全部只能进行全量搜索即扫描全表。

26 . 索引的原理:

    索引的原理大致概括为以空间换时间,数据库在未添加索引的时候进行查询默认的是进行全量搜索,也就是进行全局扫描,有多少条数据就要进行多少次查询,然后找到相匹配的数据就把他放到结果集中,直到全表扫描完。而建立索引之后,会将建立索引的KEY值放在一个n叉树上(BTree)。因为B树的特点就是适合在磁盘等直接存储设备上组织动态查找表,每次以索引进行条件查询时,会去树上根据key值直接进行搜索,次数约为log总条数,底数为页面存储数,例如一个100万数据的表,页面存储数为100,那么有索引的查询次数为3次log1000000100,但是全量搜索为100万次搜索,这种方式类似于二分法,但是这个是n分法。

27 . 数据库连接池?

27.1 应用程序直接获取数据里连接的缺点: 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出、拓机

27.2 使用数据库连接池优化程序性能 : 数据库连接池负责分配,管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。
数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中, 这些数据库连接的数量是由最小数据库连接数来设定的.无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量.连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中.

数据库连接池的最小连接数和最大连接数的设置要考虑到以下几个因素:
最小连接数:是连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费.
最大连接数:是连接池能申请的最大连接数,如果数据库连接请求超过次数,后面的数据库连接请求将被加入到等待队列中,这会影响以后的数据库操作
如果最小连接数与最大连接数相差很大:那么最先连接请求将会获利,之后超过最小连接数量的连接请求等价于建立一个新的数据库连接.不过,这些大于最小连接数的数据库连接在使用完不会马上被释放,他将被放到连接池中等待重复使用或是空间超时后被释放.

28 . durid的常用配置?

29 . TCP,UDP区别?
TCP 优点:稳定,可靠。三次握手建立连接才能通信。tcp具有确认,窗口,重传,拥塞控制机制。
缺点:慢,效率低,占用资源高。
UDP: 传输速率快,但是不安全,不可靠,可能丢包。
1.基于连接与无连接;
2.对系统资源的要求(TCP较多,UDP少);
3.UDP程序结构较简单;
4.流模式与数据报模式 ;
5.TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。

30 . spring中用到哪些设计模式?

1.工厂模式,这个很明显,在各种BeanFactory以及ApplicationContext创建中都用到了;

2.模版模式,这个也很明显,在各种BeanFactory以及ApplicationContext实现中也都用到了;

3.代理模式,在Aop实现中用到了JDK的动态代理;

4.单例模式,这个比如在创建bean的时候。

31 . 分布式事务的控制?

分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。

分布式事务解决方案:基于XA协议的两阶段提交。XA中大致分为两部分:事务管理器和本地资源管理器。其中本地资源管理器往往由数据库实现,比如Oracle、DB2这些商业数据库都实现了XA接口。而事务管理器作为全局的调度者,负责各个本地资源的提交和回滚。

最终一致性: 所谓的消息事务就是基于消息中间件的两阶段提交,本质上是对消息中间件的一种特殊利用,它是将本地事务和发消息放在了一个分布式事务里,保证要么本地操作成功成功并且对外发消息成功,要么两者都失败,开源的RocketMQ就支持这一特性。

32 . 分布式锁如何设计?

33 . 分布式session如何设计?

    基于数据库的session共享
    基于缓存的session共享
    基于文件系统

34 . zookeeper的负载均衡算法有哪些?

35 . redis和memcached的区别?

1、Redis和Memcache都是将数据存放在内存中,都是内存数据库。不过memcache还可用于缓存其他东西,例如图片、视频等等;
2、Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储;
3、虚拟内存–Redis当物理内存用完时,可以将一些很久没用到的value 交换到磁盘
4、过期策略–memcache在set时就指定,例如set key1 0 0 8,即永不过期。Redis可以通过例如expire 设定,例如expire name 10;
5、分布式–设定memcache集群,利用magent做一主多从;redis可以做一主多从。都可以一主一从;
6、存储数据安全–memcache挂掉后,数据没了;redis可以定期保存到磁盘(持久化);
7、灾难恢复–memcache挂掉后,数据不可恢复; redis数据丢失后可以通过aof恢复;
8、Redis支持数据的备份,即master-slave模式的数据备份

redis、memcache、mongoDB 对比
从以下几个维度,对redis、memcache、mongoDB 做了对比,
1、性能
都比较高,性能对我们来说应该都不是瓶颈
总体来讲,TPS方面redis和memcache差不多,要大于mongodb
2、操作的便利性
memcache数据结构单一
redis丰富一些,数据操作方面,redis更好一些,较少的网络IO次数
mongodb支持丰富的数据表达,索引,最类似关系型数据库,支持的查询语言非常丰富

3、内存空间的大小和数据量的大小
redis在2.0版本后增加了自己的VM特性,突破物理内存的限制;可以对key value设置过期时间(类似memcache)
memcache可以修改最大可用内存,采用LRU算法
mongoDB适合大数据量的存储,依赖操作系统VM做内存管理,吃内存也比较厉害,服务不要和别的服务在一起

5、可靠性(持久化)

对于数据持久化和数据恢复,

redis支持(快照、AOF):依赖快照进行持久化,aof增强了可靠性的同时,对性能有所影响

memcache不支持,通常用在做缓存,提升性能;

MongoDB从1.8版本开始采用binlog方式支持持久化的可靠性

6、数据一致性(事务支持)

Memcache 在并发场景下,用cas保证一致性

redis事务支持比较弱,只能保证事务中的每个操作连续执行

mongoDB不支持事务

7、数据分析

mongoDB内置了数据分析的功能(mapreduce),其他不支持

8、应用场景
redis:数据量较小的更性能操作和运算上

memcache:用于在动态系统中减少数据库负载,提升性能;做缓存,提高性能(适合读多写少,对于数据量比较大,可以采用sharding)

MongoDB:主要解决海量数据的访问效率问题

36 . redis支持哪些数据结构?

String、list,hash,zset,set

31 . redis是单线程的么,所有的工作都是单线程么?

cpu不是redis的瓶颈,redis的瓶颈来源于内存还有网络带宽。单线程更容易实现。

redis速度快的原因:1.绝大多数操作都是内存操作。2. 单线程实现,避免了不必要的上下文切换。3. 非阻塞IO

32 . redis的哨兵模式,一个key值如何在redis集群中找到存储在哪里?

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值