java笔记--问题总结

1. 垃圾回收算法

标记-清除算法html

标记-清除算法是最基本的算法,和他的名字同样,分为两个步骤,一个步骤是标记须要回收的对象。在标记完成后统一回收被标记的对象。这个算法两个问题。一个是效率问题,标记和清除的效率不高。第二个问题是标记-清除以后会有大量不连续的碎片空间,若是咱们须要更大的连续内存就必须GC前端

复制算法java

复制算法,不一样于标记-清除,复制算法大多数用于新生代,它须要大小相等的两块内存,每次只使用一块内存,当GC的时候会把这块内存存活的对象复制到另一块内存上面,解决了时间效率和空间碎片问题。在新生代中会把他分为三个内存一个Eden 两个Survivor默认是8比1,开始会使用一个Eden和一个Surivivor装载内存,清除时会将这两个保留的对象都保存另外在Survivor中,而且年龄加1(之后提高为老年代),若是超出了Survivor中的限制会用老年代的内存担保。mysql

标记-整理算法react

主要特色是,解决了碎片问题。标记整理算法,标记过程和第一算法同样,可是他处理的时候会让存活的对象向一边移动解决了空间碎片问题,用于老年代的处理。linux

分代收集算法nginx

分代收集算法不是新思想,只是把上面的算法结合起来了。c++

2. AtomicInteger实现原理

AtomicInteger使用value来保存值,value是volatile的,保证了可见性。git

对于get方法直接返回value,对于自增一或者添加值使用了CAS自旋锁,使用了一个死循环,若是cas返回为true就能够退出循环。对于CAS 全称是compare and swap比较和交换,CAS须要三个操做数,一个是变量内存地址,一个是excepted过时值,一个是如今要更新的值,咱们操做的时候仅当V符合旧预期的值的时候才能更新咱们新的。对于它的自增的操做,首先是卸载一个for循环里面而后得到当前的值,给这个值+1,而后进行cvs要是失败会再次Get()最新值再次写.程序员

参考:http://ifeve.com/atomic-operation/

3. synchronizedlock的区别主要有三个区别

用法区别,性能区别,锁机制的区别。

对于用法区别:synchronized能够在方法中上使用也能够在特定代码块中使用,括号中表示须要锁的对象,若是在方法上就是对该对象的锁,若是是在类的方法上就是类的锁,使用Lock必须本身用代码显示申明什么时候开启锁,什么时候关闭锁。synchronized是jvm的底层实现,而Lock是由代码执行。

对于性能的区别:ReentrantLock 功能上要多于synchronized,多了锁投票,定时锁等。若是在小规模的竞争上synchronized效率比较高,若是在大规模的竞争上synchronize就比较低而Lock基本不变、

锁的机制也不一样:synchronized得到锁和释放锁都是在块中,都是自动释放,不会引发死锁,而Lock须要本身定位释放,否则会引发死锁。在Lock中也使用了tryLock方法用非阻塞的方式获取锁。

在lock中用一个锁变量和队列维护同步。

gc停顿缘由,如何下降GC停顿

缘由:gc停顿的意思就像是在整个分析期间冻结在某个时间点上,具体的缘由是防止在分析的时候,对象引用关系还在不断的变化,若是没有GC停顿颇有可能分析不许确。

如何下降:在Serial的老年代垃圾收集器中,会把全部线程的暂停,停下来收集哪些是死亡对象。在CMS和G1中都采起了初始标记、并发标记、短暂GC停顿从新标记,初始标记会直接记录能GC ROOTS 关联的对象,在并发标记的时候有一个线程来标记,这个时候对象的发生的变化都会记录下来,在从新标记的时候会修正,这样就会下降GC停顿时间

jvm如何调优,参数怎么调?如何利用工具分析jvm状态?

合理的分配内存,分配栈和堆的内存,在堆中咱们还能够详细划分新生代和老年代的内存比例,在新生代中咱们也能够划分Eden和Surivior的内存比例(调该比例大小),合理的划份内存区域大小,能够帮助咱们jvm调优,咱们采起合适的垃圾回收器,好比在新生代启用serial垃圾回收器,在老年代采用cms并发标记,能够下降GC停顿,固然也能够尝试去采用G1垃圾回收器

jvm中类加载过程

类加载到类被卸载过程包括7个阶段

1.加载

经过类的全限定名把类文件的二进制流加入进来,经过这个字节流(这个二进制流也是咱们代理类的方法),而后经过这个二进制流把静态存储结构转化为运行时方法区的结构(不包括类变量,类变量在准备阶段),在内存中生成一个Class对象,做为方法区访问的入口。

2.验证验证是验证Class文件的字节流包含的信息是否符合当前虚拟机的要求规范,防止恶意攻击、

3.准备在方法区为类变量分配内存和设置初始值,这个时候的初始值是数据的0值,不是咱们定义的值,若是是常量的话准备阶段就会设置为咱们定义的值

4.解析将符号引用(这里的符号引用指的是字面量的形式,只须要无歧义地定位到目标)替换为直接变量

5.初始化类初始化阶段是咱们加载过程的最后一步,执行类构造器,合并static语句,有static的顺序决定。

6.使用

7.卸载

4. Springbean的加载机制,bean生成具体步骤

Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。

spring中Bean的加载机制其实就是IOC容器的初始化,好比咱们这里定义了一个IOC容器,BeanFactroy的子类ClassXMLPathApplicationContext,在他的构造函数中咱们会把xml路径写进去这个步骤就是定位,接下来就是BeanDefiniton的载入,在构造函数当中有一个refresh()的函数,这个就是载入BeanDefinition的接口,这个方法进去以后是一个同步代码代码块,把以前的容器销毁和关闭建立了一个BeanFatroy,就像对咱们的容器从新启动同样,而后咱们对BeanDefiniton载入和解析解析完毕以后会把beanDefinitionbeanName放入BeanFactoryHashMap中维护。在这里Bean已经被建立完成,而后咱们就像IOC容器索要Bean,若是是第一次索要会触发依赖注入,会递归的调用gebBean实现依赖出入.

5. 讲下java锁的原理

对于synchronized关键字,在jvm中在编译的时候在同步块的先后造成监视进入和监视退出两个字节码,这两个字节码都须要一个引用类型的参数来指定要锁定和解锁的对象,若是指定了的话就使用指定的对象,若是没有指定看是类方法仍是对象方法来决定,在执行监视进入的指令的时候,会判断可否进入,进入成功以后会把锁计数器加1,若是不成功就会继续等待和其余的线程竞争,出锁的时候会把锁计数器减1变为0,也就是释放了锁。在这里要说明一点java的线程时映射到系统原生线程之上,若是要阻塞或者唤醒一个线程都须要操做系统帮忙,这就须要从用户态转换到核心态中,所以状态转换须要耗费不少的处理器时间。有可能比用户的代码执行时间还长。在jdk1.6以后对synchronized优化是很是的号的,好比锁粗化,锁自旋,锁消除。轻量级锁和偏向锁。

而对于ReentrantLock是代码上的实现

6. 线程和进程的区别

进程是一段正在执行的程序,线程也叫做”轻量级进程“,他是程序执行的最小单元,一个进程能够有多个线程,各个线程之间共享程序的内存空间(好比说堆空间)及一些进程级的资源,进程和进程之间不能共享内存只能共享磁盘文件,线程也有4中状态:就绪,运行,挂起,死亡。

(新版本)进程是程序执行时的一个实例,从内核的观点看,进程的目的就是担当分配系统资源的基本单位。

线程是进程的一个执行流,是cpu调度和分配的基本单位,它是比进程更小的能独立运行的基本单位。一个进程由几个线程组成,线程和同属一个进程的其余的线程共享进程所拥有的所有资源。

进程-资源分配的最小单位。线程-程序执行的最小单位。

进程由独立的空间地址,线程没有单独的地址空间同一进程内的共享进程的地址空间,只有本身独立的堆栈和局部变量。对于咱们来讲实现一个多线程的任务比实现一个多进程的任务好,

7. 为何分配线程比分配通常的对象更须要花费更大的代价?

首先他的资源很是“节俭”。咱们知道,在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,创建众多的数据表来维护它的代码段,堆栈段和数据段,这是一种“昂贵”的多任务工做方式。而运行一个进程中的多个进程,他们彼此之间使用相同的地址空间,共享进程内的大部分数据,启动一个进程的时间远大于一个线程的时间。

(1)地址空间:进程内的一个执行单元;进程至少有一个线程;它们共享进程的地址空间;而进程有本身独立的地址空间;

(2)资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源

(3)线程是处理器调度的基本单位,但进程不是.

8. Spring AOP是怎么实现

首先简单说一下Spring AOP几个比较重要的名词:

通知:定义在链接点作什么,为切面加强提供织入接口,意思就是说加强的内容以及加强的方式

切点:PointCut:决定通知应用于什么方法上或者类上。(点:方法或者类)

通知器:链接切点和通知结合起来,可让咱们知道那个通知应用于哪一个结点之上,这个结合为应用使用Ioc容器配置AoP应用

开始咱们使用AOP的时候是用得java编写的切面通知使用XML配置,后面咱们摒弃了采用@AspectJ注解对其进行标注

而后AOP的实现原理有一个ProxyFactoryBean(代理工厂),这个ProxyFactoryBea是在Spring Ioc环境之中,建立AOP应用的最底层。在ProxyFactoryBean中咱们会配置好通知器Advisor,在ProxyFactory须要为目标对象生成代理对象。ProxyFactory有一个getObject方法,在咱们IOC容器中若是获取这个bean会自动调用这个方法,首先第一步初始化通知器链,通知器链只会初始化一次,使用标志位判断,遍历通知器,把全部通知器加入拦截器链,接下来就是代理对象的生成,利用目标对象以及拦截器咱们能够正确的生成代理对象,这里生成代理对象有两种方法一种是jdk一种是cglib,在获得AopProxy代理对象以后,咱们首先会根据配置来对拦截器是否与当前的调用方法想匹配,若是当前方法匹配就会发挥做用,他会遍历Proxy代理对象中设置拦截器链的全部拦截器,拦截器调用完成以后才是目标对象的调用,这个时候会有一个注册机制,在拦截器中运行的拦截器,会注册,咱们就不须要再判断。Aop的源代码中也大量使用了IOC容器,好比从IOC中找到通知器。

9. SpringMVC的主要流程

首先咱们会在web.xml中配置DispathcerServlet,这个就是SpringMVC的入口,DispathcerServlet的父类FrameWorkServlet首先会初始化WebApplicationContext,DispacherServlet初始化了9个组件,初始完毕后咱们开始进入,FramkeworkServlet中作了三件事一个是调用doService模板方法具体处理请求。将当前全部的请求都合并在一个方法里面和咱们的httpServlet作法有点不一样,在DispathcerServlet中有一个doService的方法,其中调用了doDispatch这也是最核心的首先根据request找到Handler,根据Handler找到了HderAdapter,用HandlerAdapter处理Handler其中包含一些参数的处理,处理完成后就行方法调用以后获得结果真后把View渲染给用户或者把数据发给用户。

详细版本:

1.输入一个网址,好比http请求,首先咱们tomcat服务器,会对请求建立出咱们request和response,而后就交给咱们对应的servlet处理。

10. 建立线程方式

实现runnable接口重写run方法,继承Thread,利用线程池来建立。

11. 想让全部线程都等到一个时刻同时执行有哪些方法

CountDownLatch:CountDownLatch首先咱们在构造函数当中传入了一个标志值,而后在须要阻塞的地方调用await(),直到其余线程把countDown减小完。这个是不可重用的。

CyclicBarrier:和他的名字同样栅栏,咱们对他的构造函数传入一个栅栏值,在须要阻塞的地方调用await的时候咱们就对其基础值加一,直到等于栅栏值。调用CylicBarrier的reset方法能够对他进行重置。

Semaphore信号量:Semaphore能够同时控制访问的线程个数,若是须要这个资源咱们会acquire()以阻塞的方式去请求,若是没有可用的信号量,就等待,release释放信号量,这个机制有点相似于锁。

jdk1.7中提供了一个同步器Phaser,做用和countdownLatch,CyclicBarrier相似,但PHaser的使用方式更为灵活。使用register注册方法递增计数器,使用arriveAndDeregister()方法来递减计数器,使用arriveAndAwaitAdvane()方法阻塞线程,当计数器归0唤醒。

12. volatile的做用

参看博客:http://blog.csdn.net/libing13820393394/article/details/48582999

第一:volatile是Java虚拟机提供的最轻量级的同步机制,使变量对全部的线程可见,保证了可见性,可是并不能保证它的原子性。

第二个:禁止指令重排序优化。普通变量仅仅保证在该方法全部依赖赋值结果的地方都能获取到正确的结果,而不能保证变量赋值操做的顺序与程序代码中的执行同样。从硬件的方面来讲,并非指令任意重拍,他只是把多条指令不安程序规定顺序分发给电路处理单元,好比说2*3+5 2*3之间是有依赖,5就能够排到他们前面。volatile会帮助咱们加入内存屏障防止重排序。volatile读操做性能消耗与普通变量几乎没区别,写操做会慢一些,由于它须要在本地代码中插入许多内存屏障指令来保证处理器不发生乱序执行。

注意:对于volatile修饰的变量,jvm只是保证从主内存加载到线程的工做的内存是最新的

13. 谈一谈java内存模型

(1)java虚拟机规范试图定义一种JAVA内存模型来屏蔽掉各类硬件和操做系统的内存访问的差别。

(2)java内存模型的主要目标是定义程序中各个变量的访问规则,这里的变量不包含局部变量和方法参数,而是指的是实例字段、静态字段、和构成数组对象的元素。

(3)java内存模型规定了全部的变量都存储在主内存中,而线程内的局部变量在本身的工做内存中,而且还有被该线程使用到的变量的主内存 的副本拷贝,线程对变量的操做(读取、赋值)都在工做内存中进行,不能直接读写主内存的变量,不一样的线程没法直接访问对方工做内存的变量,线程键的变量值的传递须要经过主内存来完成,在内存模型中比较重要的就是工做线程和主内存的交互。

内存之间的交互:

java内存模型定义的操做:

Lock (锁定)

Unlock(解锁)

Read(读取)

Load(载入)

Use(使用)

Assign(赋值)

Store(存储)

Write(写入)

变量从主内存到工做内存:按照顺序执行read load操做

变量从工做内存到主内存:按照顺序执行Store write操做

重排序:

包括:编译器优化重排序、指令级并行重排序、内存系统重排序

14. 何时使用LinkedList?

首先分写LinkedList和ArrayList的不一样,在常常插入和删除的时候,在实现栈和队列的时候,不适合随机查找元素。

15. Object有哪些方法(九大方法),clone是深复制仍是浅复制,finalize通常在何时使用:

wait,notify,notifyall,clone,getclass,toString,equals,hashcode,finalize。

一、Clone()方法

private保护方法,实现对象的浅复制,只有类实现了Clonable接口才能够调用该方法,不然抛出CloneNotSupportException。clone是浅复制,复制完成后其中的变量引用仍是和之前的同样,若是要实现深复制须要咱们把全部的变量引用都递归复制一次,而后再赋值。(或者额使用序列化,也能够实现深拷贝)若是咱们要本身实现clone()方法必需要实现克隆接口clonable。

二、Equals()方法

在object中与==是同样的,子类通常须要重写该方法

三、hashCode()方法

该方法用于哈希查找,重写了equals方法通常都要重写hashcode方法,这个方法在一些具备哈希功能的collection中使用

四、getClass()方法

final方法,得到运行时的类型

五、Wait()方法

使得当前的线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具备该对象的锁。Wait方法会一直等待,直到得到锁(到了睡眠的时间间隔也会唤醒本身)或者被中断掉。

调用该方法,当前的线程会进入到睡眠的状态,直到调用该对象的notify方法、notifyAll方法、调用interrupt中断该线程,时间间隔到了。

六、Notify()方法

唤醒在该对象上的等待的某个线程

七、notifyAll()方法

唤醒在该对象上的等待到全部的线程

八、toString()方法

把对象转换成string类型进行输出

九、finalize()方法

finalize在咱们垃圾回收器回收这个对象的时候工做,能够作一些后续的工做,即进行一些必要的清理和清除的工做,好比说关闭流。固然咱们也能够在这个里面对咱们即将被回收的对象逃出回收。这里须要注意的是系统只会调用一次finalize()方法。可是通常咱们不推荐使用这个方法,由于这个方法是为了对开始C和C++程序员的一种妥协,由于C中有析构函数,这个方法运行代价高,不肯定大,咱们仍是会推荐使用try{}finally,他作的方法try{}finally均可以作。

16. 如何管理线程(主要介绍各类线程池的实现)

使用线程池来管理线程

Java中实现多种线程池

咱们使用executors工厂产生咱们的线程池,当线程池达到负载的时候会在咱们线程池管理的Runnable阻塞队列中等待,不会像线程那样竞争CPU

第一种 newFixedThreadPool,和它的名字同样这是一个固定线程池,咱们能够设置基本大小也就是咱们没有任何任务执行的时候的大小,最大大小,只有在工做队列满了才能达到最大大小。

第二种 newCachedThreadPool这种线程池把大小设置为Integer.MAX_VALUE,基本大小设置为0,空闲超时设置1分钟,这种线程池能够无限扩展,而且当需求下降时会自动收缩。

第三种 newSingleThreadPool这种线程池把基本大小设置为1,最大大小都设置为1,只容许同一时刻一个线程。

固定线程池和单线程池固定默认使用的是阻塞队列无界的LinkedBlockingQueue,在这个阻塞队列中能够无限增加。可是对于咱们的newCachedThreadPool来讲他的线程池是无限大的,不须要阻塞等待,咱们这里使用的是SynchronousQueue来避免排队,其实这个东西不是一个队列,是直接在线程之间进行移交,当线程池的大小小于所须要的时候,要么建立一个要么拒绝一个。咱们通常在使用的时候能够扩展,使用使用信号量来控制提交速率。

17. 如何让线程A等待线程B结束

1.使用join方法能够等待A线程结束,或者单线程池中 阻塞队列的方式让A先得到单线程池的线程,而后B一直阻塞,知道A释放本身的线程。

18. 如何优化jvm参数

,首先设置堆的大小,通常设置xmx和xms大小相同,若是老年代容易溢出能够扩充老年代,也要适当的调整永久代大小,选择本身合适的收集器,调整新生代对象年龄阀值等。

19. 什么是守护线程

线程会分为两种:

普通线程和守护线程。在JVM启动时建立的全部线程中,除了主线程其余都是守护线程,好比说垃圾回收器就是守护线程,当普通线程所有退出的时候守护线程也会退出,咱们本身也能够手动设置手动线程在线程启动以前,可是咱们应该尽量少使用守护线程,由于咱们不多有操做能够在不进行清理就能够安全地抛弃,好比说I/O操做。

20. TCP如何控制拥塞

拥塞控制就是防止过多的数据注入网络中,这样能够使网络中的路由器或链路不致过载。

发送方维持一个叫作拥塞窗口cwnd(congestion window)的状态变量。

为了防止cwnd增加过大引发网络拥塞,还需设置一个慢开始门限ssthresh状态变量。ssthresh的用法以下:

cwnd时,使用慢开始算法。也就是乘法算法

cwnd>ssthresh时,改用拥塞避免算法。也就是加法算法

cwnd=ssthresh时,慢开始与拥塞避免算法任意。

当出现拥塞的时候就把心的门限值设为此时窗口大小的通常,窗口大小设置为1,再从新执行上面的步骤。

当收到连续三个重传的时候这就须要快重传和快恢复了,当收到连续三个重传这个时候发送方就要重传本身的信息,而后门限减半可是这个时候并非网络阻塞,窗口只会减半执行拥塞避免算法。

21. ThreadLoacl?

咱们使用ThreadLocal为每一个使用该类型的变量提供了一个独立的副本,具体的实现是在每一个线程中保存了一个ThreadLocalMap,这个ThreadLoaclMap会在咱们第一次使用ThreadLoal中的set方法建立出来,set方法就是保存在ThreadLocalMap中,该变量为key,值为value,get方法也从这个HashMap中找。

22. OSI网络模型?

网卡在哪一层(物理层)

交换机在哪一层(链路层)

路由器在哪一层(网络层)

传输TCP

会话 SQL

表示 IMG

html在应用层

23. HTTP1.0Http1.1区别?

1.0默认是屡次tcp链接屡次请求,而后增长了keep alive功能,可是必须在request Header手动增长Connection:keepalive

1.1是一次tcp链接屡次请求,新的persistence功能

24. POSTGET方法的区别?

长的说:

对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);

而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

也就是说,GET只须要汽车跑一趟就把货送到了,而POST得跑两趟,第一趟,先去和服务器打个招呼“嗨,我等下要送一批货来,大家打开门迎接我”,而后再回头把货送过去。

由于POST须要两步,时间上消耗的要多一点,看起来GET比POST更有效。所以Yahoo团队有推荐用GET替换POST来优化网站性能。但这是一个坑!跳入需谨慎。为何?

1. GET与POST都有本身的语义,不能随便混用。

2. 据研究,在网络环境好的状况下,发一次包的时间和发两次包的时间差异基本能够无视。而在网络环境差的状况下,两次包的TCP在验证数据包完整性上,有很是大的优势。

3. 并非全部浏览器都会在POST中发送两次包,Firefox就只发送一次。

1.get是从服务器上获取数据,post是向服务器传送数据。

2.get是经过URL来传递数据,POST是经过表单传递,所以get数据限制在1024k,而POST没有限制

3.在java服务器端get是经过request.qureySting post经过request.getParameterNames和reque.getParameterValue

4.get是安全的,幂等的 POST即不安全又不幂等(屡次操做和一次操做同样)

在rest中设计的话,通常get用来查询数据,POST用来添加数据,PUT用来更新数据,Delete用来删除数据

25. filter执行顺序?

多个filter的执行顺序是web.xml中的配置顺序

影响SQL执行效率的因素?

1.is null和is not null

2.通配符的like

3.order by

4.not

5.in和exists

GBK和UTF-8的区别

GBK包含所有中文字符; UTF-8则包含全世界全部国家须要用到的字符。

GBK的文字编码是双字节来表示的,即不论中、英文字符均使用双字节来表示,只不过为区分中文,将其最高位都定成1。

至于UTF-8编码则是用以解决国际上字符的一种多字节编码,它对英文使用8位(即一个字节),中文使用24位(三个字节)来编码。对于英文字符较多的论坛则用UTF-8节省空间。

UTF8是国际编码,它的通用性比较好,外国人也能够浏览论坛 GBK是国家编码,通用性比UTF8差,不过UTF8占用的数据库比GBK大~

26. stringBufferStringBuilder

1.三者在执行速度方面的比较:StringBuilder >  StringBuffer  >  String

servlet和Filter的实现原理

StringBuffer是线程安全的,St不是线程安全的,内部的实现是使用char数

27. 什么是rest

一次网站访问的全过程:

楼主提到TCP/IP分层的时候用的是网络接口层,那么楼主的TCP/IP分层概念应该是:应用层、传输层、网络层、网络接口层(包含了七层模型中的数据链路层和物理层)。

我尝试回答一下楼主的问题,但愿你们继续拍砖,若是访问www.163.COM这个网站,那么他的主要过程应该是:

1、主机向DNS服务器发起域名解析请求,以获得相对应的IP地址

2、应用层应用HTTP协议发送数据

3、数据到达传输层封装成数据段,主机使用1024之后的随机源端口号,目标端口号为80

4、数据段到达网络层封装成数据包,加入主机源IP地址和目标IP地址

5、数据包到达网络接口层首先封装成数据帧,加入源MAC地址和目标MAC地址(注:此目标MAC地址为本地网关的MAC地址,源和目的MAC地址在数据转发的过程当中,会由路由器不断的改变)。封装后将数据转换为物理层的数据流,经过互联网发送至目标服务器。

28. 何时抛出InvalidMonitorStateException异常?为何?

调用 wait ()/notify ()/notifyAll ()中的任何一个方法时,若是当前线程没有得到该对象的锁,

那么就会抛出 IllegalMonitorStateException 的异常

也就是说程序在没有执行对象的任何同步块或者同步方法时,

仍然尝试调用 wait ()/notify ()/notifyAll ()时。因为该异常是 RuntimeExcpetion 的子类,

因此该异常不必定要捕获(尽管你能够捕获只要你愿意

做为 RuntimeException,此类异常不会在 wait (),notify (),notifyAll ()的方法签名说起。

29. Collections.synchronizedXX 方法的原理

返回了一个同步容器,在这个同步容器中的全部方法都有一个锁为当前对象或者指定锁的同步块,用这种阻塞同步的方法可让咱们容器同步

30. 什么是Future

Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时能够经过get方法获取执行结果,该方法会阻塞直到任务返回结果。

1.cancel方法用来取消任务

2.isCancelled方法表示任务是否被取消成功,若是在任务正常完成前被取消成功,则返回 true。

3.isDone()表示是否完成

4.get()得到执行结果,这个方法会一直阻塞

5.在时间范围内获取执行结果

FutureTask是Future的实现类

31. 说出数据链接池的工做机制是什么?

J2EE服务器启动时会创建必定数量的池链接,并一直维持很多于此数目的池链接。

   调用:客户端程序须要链接时,池驱动程序会返回一个未使用的池链接并将其表记为忙。若是当前没有空闲链接,池驱动程序就新建必定数量的链接,新建链接的数量有配置参数决定。

释放:当使用的池链接调用完成后,池驱动程序将此链接表记为空闲,其余调用就能够使用这个链接。

数据库链接池在初始化时将建立必定数量的数据库链接放到链接池中,这些数据库链接的数量是由最小数据库链接数来设定的。不管这些数据库链接是否被使用,链接池都将一直保证至少拥有这么多的链接数量。链接池的最大数据库链接数量限定了这个链接池能占有的最大链接数,当应用程序向链接池请求的链接数超过最大链接数量时,这些请求将被加入到等待队列中。

数据库链接池的最小链接数和最大链接数的设置要考虑到下列几个因素:

1) 最小链接数是链接池一直保持的数据库链接,因此若是应用程序对数据库链接的使用量不大,将会有大量的数据库链接资源被浪费;

2) 最大链接数是链接池能申请的最大链接数,若是数据库链接请求超过此数,后面的数据库链接请求将被加入到等待队列中,这会影响以后的数据库操做。

3) 若是最小链接数与最大链接数相差太大,那么最早的链接请求将会获利,以后超过最小链接数量的链接请求等价于创建一个新的数据库链接。不过,这些大于最小链接数的数据库链接在使用完不会立刻被释放,它将被放到链接池中等待重复使用或是空闲超时后被释放。

32. 存储过程和函数的区别

存储过程是用户定义的一系列sql语句的集合,涉及特定表或其它对象的任务,用户能够调用存储过程,而函数一般是数据库已定义的方法,它接收参数并返回某种类型的值而且不涉及特定用户表。

33. 事务是什么?

事务是做为一个逻辑单元执行的一系列操做。

34. 游标的做用?如何知道游标已经到了最后?

游标用于定位结果集的行,经过判断全局变量@@FETCH_STATUS能够判断是否到了最后,一般此变量不等于0表示出错或到了最后。

35. 系统进程间通讯的方式

管道( pipe ):管道是一种半双工的通讯方式,数据只能单向流动,并且只能在具备亲缘关系的进程间使用。进程的亲缘关系一般是指父子进程关系。

命名管道 (named pipe) 命名管道也是半双工的通讯方式,可是它容许无亲缘关系进程间的通讯。

信号量( semophore ) 信号量是一个计数器,能够用来控制多个进程对共享资源的访问。它常做为一种锁机制,防止某进程正在访问共享资源时,其余进程也访问该资源。所以,主要做为进程间以及同一进程内不一样线程之间的同步手段。

消息队列( message queue ) 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。

信号 ( sinal ) 信号是一种比较复杂的通讯方式,用于通知接收进程某个事件已经发生。

共享内存( shared memory ) :共享内存就是映射一段能被其余进程所访问的内存,这段共享内存由一个进程建立,但多个进程均可以访问。共享内存是最快的 IPC 方式,它是针对其余进程间通讯方式运行效率低而专门设计的。它每每与其余通讯机制,如信号量,配合使用,来实现进程间的同步和通讯。

套接字( socket ) 套解口也是一种进程间通讯机制,与其余通讯机制不一样的是,它可用于不一样及其间的进程通讯。

36. jvm调优:内存溢出和内存泄露:

溢出解决:

1.在代码中减小没必要要的实例构造

2.设置堆和永久代的大小 -xms堆最小 -xmx堆最大

内存泄露:

内存泄露不能经过配置解决代码的问题。好比资源在使用完毕后没有释放,一些对象存在无效引用咱们不能回收。

37. httphttps的区别

http协议是无状态的明文传输,Https而SSL+HTTP协议构建的可进行加密传输。https的服务器必须向CA申请一个证实服务器用途的证书,而客户端经过该证书确认服务器,因此银行都是https,全部的通信都是在密钥加密的状况下,而密钥则是经过证书交换,因此第三方拦截的数据没有密钥也没有用。

SSL用以保障在Internet上数据传输之安全,利用数据加密(Encryption)技术,可确保数据在网络上之传输过程当中不会被截取及窃听。

38. 虚拟机性能监控情况

jps:显示系统内全部进程的信息。

jstat:收集虚拟机各类运行状态信息的命令行工具。 -gc,监视java堆 -class 就是监视类加载,还能够监视编译情况。

jinfo:java配置信息工具。

jmap:用于生成堆转储快照 有些选项只能在linux下才能看见。

jhat:配合jmap。

jstack:堆栈追踪。

39. Servlet生命周期

1.加载:在Servlet容器启动的时候会经过类加载器加载咱们的Servlet的Class文件。

2.建立:在建立过程的时候若是没有在web.xml文件中使用load-on-startup咱们在第一次访问咱们的Servlet的时候会初始化实例,若是配置了这个而且大于1会在容器启动的时候就建立。

3.初始化:init()初始化的方法只会被调用一次。在咱们实例化被建立以后就会执行初始化。

4.处理客户请求:service()在Servlet的service方法中会根据不一样的http方法来调用。

5.卸载:destroy()当咱们Servlet须要被卸载的时候就会调用咱们的destory()方法,随后垃圾回收器会回收。

40. Minor GCFULL GC

当咱们须要向新生代中分配内存时出现不足的状况:会出现Minor GC,在新生代中 都是朝生夕灭的对象,频率比较高。Minor GC发生在新生代。

FULL GC指在老年代发生的GC,通常状况下出现了FULL GC都会伴随着一次Minor GC。

为何MinorGC 和FULL GC速度有差距呢?

在Minor GC中使用的copy算法,在FullGC中使用的是标记清除 或者标记整理算法。

copy算法是用空间换时间 mark(标记)和copy(复制)是一个动做。

可是mark-sweap或mark-compact都是分为两个阶段,先标记再清除是两步骤。

因此Minro GC速度会快于FullGC。

41. JVM调优问题

对于JVM调优的重点是垃圾回收和内存管理。

垃圾回收咱们能够使用咱们的cms垃圾回收器。

对于内存管理有:

永久代溢出、栈溢出、堆溢出的状况

永久代溢出:

针对永久代溢出在JVM默认状况只有64M的永久代大小,不少东西都须要咱们永久代区内存,尤为是使用Spring等框架的时候会有cglib的动态字节码生成class,都会存储在咱们的永久代。因此咱们须要扩充永久代防止内存溢出。

堆溢出:

对于堆溢出咱们也是比较常见的好比说咱们使用容器的时候没有释放内存颇有可能就会致使堆溢出,须要动态扩展。

栈溢出:

对于栈咱们也能够设置提升。

42. 单例模式

1)恶汉式的单例模式

利用静态static的方式进行实例化,在类被加载时就会建立实例。

/**

 * 饿汉式实现单例模式

 */

public class Singleton {

  private static Singleton instance = new Singleton();//在类加载时实例单例对象

    private Singleton() {//私有的构造器

    }

    public static Singleton getInstance() {//返回一个实例对象

        return instance;

    }

}

(2)懒汉式实现单例模式

在被第一次引用时才去建立对象。

/**

 * 懒汉式实现单例模式

 */

public class Singleton {

    private static Singleton instance;//建立私有的静态变量

    private Singleton() {//私有的构造函数

    }

        // synchronized方法,多线程状况下保证单例对象惟一

public static synchronized Singleton getInstance() {

//若是实例对象为空,就从新去实例化

        if (instance == null) {

            instance = new Singleton();

        }

        return instance;

    }

}

分析:这中方法的实现,效率不高,由于该方法定义为同步的方法。

(3)双重锁实现的单例模式double check

/**

 * DCL实现单例模式

 */

public class Singleton {

    private static valotile Singleton instance = null;//这里要加入valotile关键字,避免指令重排序,  可能先赋值可是没有分配内存

    private Singleton() {

    }

    public static Singleton getInstance() {

        // 两层判空,第一层是为了不没必要要的同步

        // 第二层是为了在null的状况下建立实例

        if (instance == null) {

            synchronized (Singleton.class) {

                if (instance == null) {

                    instance = new Singleton();

                }

            }

        }

        return instance;

    }

}

分析:资源的利用率较高,在须要的时候去初始化实例,并且能够保证线程的安全,该方法没有去进行同步锁,效率比较好。

(4)静态内部类实现单例模式

/**

 * 静态内部类实现单例模式

 */

public class Singleton {

    private Singleton() {

}

//返回实例的方法

    public static Singleton getInstance() {

        return SingletonHolder.instance;

    }

    /**

     * 静态内部类

     */

private static class SingletonHolder {

    //静态私有的实例对象

        private static Singleton instance = new Singleton();

    }

}

分析:第一次加载类时不会去初始化instance,只有第一次调用getInstance()方法时,虚拟机才会加载内部类,初始化instance

能够保证线程的安全,单例对象的惟一,延迟了单例的初始化。

(5)枚举单例

/**

 * 枚举实现单例模式

 */

public enum SingletonEnum {

    INSTANCE;//直接定义一个实例对象

    public void doSomething() {

        System.out.println("do something");

    }

}

分析:枚举实例的建立是线程安全的,即便反序列化也不会生成新的实例,在任何的状况下都是单例的。

43. 设计模式6大原则

1.单一职责。2.里氏替换 3.依赖致使4接口隔离5.迪米特法则6.开闭原则。

44. XMLJSON优缺点

XML的优势

A.格式统一,符合标准;

B.容易与其余系统进行远程交互,数据共享比较方便。

      C.可读性高

XML的缺点

 A.XML文件庞大,文件格式复杂,传输占带宽;

 B.服务器端和客户端都须要花费大量代码来解析XML,致使服务器端和客户端代码变得异常复杂且不易维护;

 C.客户端不一样浏览器之间解析XML的方式不一致,须要重复编写不少代码;

 D.服务器端和客户端解析XML花费较多的资源和时间。

JSON的优缺点

JSON的优势:

A.数据格式比较简单,易于读写,格式都是压缩的,占用带宽小;

B.易于解析,客户端JavaScript能够简单的经过eval()进行JSON数据的读取;

      C.支持多种语言,包括ActionScript, C, C#, ColdFusion, Java, JavaScript, Perl, PHP, Python, Ruby等服务器端语言,便于服务器端的解析;

D.在PHP世界,已经有PHP-JSON和JSON-PHP出现了,偏于PHP序列化后的程序直接调用,PHP服务器端的对象、数组等能直接生成JSON格式,便于客户端的访问提取;

E.由于JSON格式能直接为服务器端代码使用,大大简化了服务器端和客户端的代码开发量,且完成任务不变,而且易于维护。

JSON的缺点

A.没有XML格式这么推广的深刻人心和喜用普遍,没有XML那么通用性;

B.JSON格式目前在Web Service中推广还属于初级阶段。

       C:可读性低。

45. 四种读取XML文件读取的办法

1.DOM生成和解析XML文档

为XML文档的已解析版本定义了一组接口。解析器读入整个文档,而后构建一个驻留内存的树结构。

优势:整个文档树在内存中,便于操做;支持删除,修改,从新排列等。

缺点:  把整个文档调入内存,存在不少无用的节点,浪费了时间和空间。

2.SAX为解决DOM

一、边读边解析,应用于大型XML文档

二、只支持读

三、访问效率低

四、顺序访问

3.DOM4J生成和解析XML文档(解析工具) 性能最好 SUM的JAXM也大量采用DOM4J

HIBERNATE采用DOM4J

虽然DOM4J表明了彻底独立的开发结果,但最初,它是JDOM的一种智能分支。它合并了许多超出基本XML文档表示的功能,包括集成的XPath支持、XML Schema支持以及用于大文档或流化文档的基于事件的处理。它还提供了构建文档表示的选项,它经过DOM4J API和标准DOM接口具备并行访问功能。从2000下半年开始,它就一直处于开发之中。

    为支持全部这些功能,DOM4J使用接口和抽象基本类方法。DOM4J大量使用了API中的Collections类,可是在许多状况下,它还提供一些替代方法以容许更好的性能或更直接的编码方法。直接好处是,虽然DOM4J付出了更复杂的API的代价,可是它提供了比JDOM大得多的灵活性。

    在添加灵活性、XPath集成和对大文档处理的目标时,DOM4J的目标与JDOM是同样的:针对Java开发者的易用性和直观操做。它还致力于成为比JDOM更完整的解决方案,实如今本质上处理全部Java/XML问题的目标。在完成该目标时,它比JDOM更少强调防止不正确的应用程序行为。

    DOM4J是一个很是很是优秀的Java XML API,具备性能优异、功能强大和极端易用使用的特色,同时它也是一个开放源代码的软件。现在你能够看到愈来愈多的Java软件都在使用DOM4J来读写XML,特别值得一提的是连Sun的JAXM也在用DOM4J.

4.JDOM

JDOM

优势:①是基于树的处理XML的Java API,把树加载在内存中

        ②没有向下兼容的限制,所以比DOM简单

        ③速度快,缺陷少

        ④具备SAX的JAVA规则

缺点:

     ①不能处理大于内存的文档

     ②JDOM表示XML文档逻辑模型。不能保证每一个字节真正变换。

     ③针对实例文档不提供DTD与模式的任何实际模型。

     ④不支持与DOM中相应遍历包。

最适合于:JDOM具备树的便利,也有SAX的JAVA规则。在须要平衡时使用

46. 如何防止Sql注入

有两种办法

1.第一种消毒,经过正则匹配过滤请求数据中可能注入的SQL。

2.使用预编译手段preparedStatemengt。

47. DB第一范式,第二范式,第三范式

第一范式:没一列属性不可再分,没有多值属性

第二范式:在符合第一范式的基础上,存在主键

第三范式:在符合第二范式的基础上,非关键字独立于其余的非关键字,而且依赖关键字。不能存在传递依赖。

48. publicprotectedprivate默认权限

private:用于修饰类和方法,只容许该类访问。

默认:只容许在同一个类和同一个包中进行访问。

protected:用于修饰类和方法,容许该类和子类访问以及同一个包中访问。

public:用于修饰类和方法,容许该包下面和其余包的访问,即在全局范围均可以访问。

49. 数据库事务

事务的特性:

原子性:事务是不可再分的;

一致性:事务的实行先后,数据库的状态保持一致;

隔离性:事务的并发访问,事务之间的执行互不干扰;

持久性:事务结束后数据永久保存在数据库中。

什么是脏读?

脏读就是一个事务读取了该数据而且对该数据作出了修改,另外一个事务也读取了该修改后的数据可是前一个事务并无提交,这是脏数据。

读取到保存在数据库内存中的数据。

什么是不可重复读?

一个事务:在同一个事务中读取同一数据,获得的内容不一样。一个事务读取另一个事务更新的数据,致使二次的查询的数据不一致。

什么是幻读?

幻读是当事务不独立发生的。好比一个事务删除了全部数据,另外一个事务又插入了一条,那么第一个事务的用户会发现表中尚未修改的数据行。一个事务读取到另一个事务提交的数据,致使查询的结果不一致的问题。

数据库的隔离级别:

Read uncommitted:未提交读:三中都有可能发生

Read committed :已提交读 避免脏读

Repeated read:重复读:避免脏读 不可重复读

Serializable:串行化读   均可以免

50. WebService究竟是什么

一言以蔽之:WebService是一种跨编程语言和跨操做系统平台的远程调用技术。

所谓跨编程语言和跨操做平台,就是说服务端程序采用java编写,客户端程序则能够采用其余编程语言编写,反之亦然!跨操做系统平台则是指服务端程序和客户端程序能够在不一样的操做系统上运行。

所谓远程调用,就是一台计算机a上的一个程序能够调用到另一台计算机b上的一个对象的方法,譬如,银联提供给商场的pos刷卡系统,商场的POS机转帐调用的转帐方法的代码实际上是跑在银行服务器上。再好比,amazon,天气预报系统,淘宝网,校内网,百度等把本身的系统服务以webservice服务的形式暴露出来,让第三方网站和程序能够调用这些服务功能,这样扩展了本身系统的市场占有率,往大的概念上吹,就是所谓的SOA应用。

其实能够从多个角度来理解WebService,从表面上看,WebService就是一个应用程序向外界暴露出一个能经过Web进行调用的API,也就是说能用编程的方法经过Web来调用这个应用程序。咱们把调用这个WebService的应用程序叫作客户端,而把提供这个WebService的应用程序叫作服务端。从深层次看,WebService是创建可互操做的分布式应用程序的新平台,是一个平台,是一套标准。它定义了应用程序如何在Web上实现互操做性,你能够用任何你喜欢的语言,在任何你喜欢的平台上写Web service ,只要咱们能够经过Web service标准对这些服务进行查询和访问。

   WebService平台须要一套协议来实现分布式应用程序的建立。任何平台都有它的数据表示方法和类型系统。要实现互操做性,WebService平台必须提供一套标准的类型系统,用于沟通不一样平台、编程语言和组件模型中的不一样类型系统。Web service平台必须提供一种标准来描述Web service,让客户能够获得足够的信息来调用这个Web service。最后,咱们还必须有一种方法来对这个Web service进行远程调用,这种方法实际是一种远程过程调用协议(RPC)。为了达到互操做性,这种RPC协议还必须与平台和编程语言无关。

51. java中锁的优化

1.减小锁持有的时间,能够减小其它线程的等待时间,不能让一个线程一直控制着某个锁不释放,致使竞争加重。

2.减小锁的粒度,合适的锁的代码块,能够减小竞争,控制锁的范围。

3.锁分离,将锁安功能划分,好比读写锁,读读不互斥,读写互斥,写写互斥,保证了线程的安全,提升了性能。好比阻塞队列中的take和put

4.锁粗化,若是对同一个锁不停的进行请求,同步和释放,这个消耗是很是的大的,因此适当的时候能够粗化。

5.锁消除,编译器能够帮助咱们优化好比一些代码根本不须要锁。

52. 虚拟机内的锁优化

1.偏向锁:偏向当前已经占有锁的线程,在无竞争的时候,以前得到锁的线程再次得到锁时,会判断是否偏向锁指向我,那么该线程将不用再次得到锁,直接进入同步块。

2.轻量级锁:偏向锁失败后,利用cas补救补救失败就会升级为重量级锁。

3.自旋锁:会作空操做,而且不停地尝试拿到这个锁。

53. java中一亿个数找前10000个最大的

先利用Hash法去重复,去除大量的以后 而后等量的分红100 用小顶堆 来得到10000个,再把全部的1万个都合在一块儿就OK

54. java中线程的状态

java中的线程的状态有5种(新建、就绪、运行、阻塞、结束)

1.新建:建立后还没有启动的线程处于这种状态,新建出一个线程对象。

2.就绪状态:当针对该对象掉用了start()方法,该线程等待获取CPU的使用权

3.运行状态:在就绪状态下,得到了CPU处于运行状态。

4.阻塞:

等待阻塞:运行的线程执行wait方法,JVM会把该线程放入等待池

同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被其余的线程锁占用,则jvm会把该线程放入锁池中。

其余阻塞:运行的线程在执行sleep()方法或者join()方法时,或者发出IO请求,JVM会把线程置为阻塞状态。

5.结束:

也就是咱们的死亡,代表线程结束。

55. Maven的生命周期

maven有三套相互独立的生命周期

1.clean生命周期

pre-clean,clean,post-clean

2.default生命周期构建项目

1.validate:验证工程是否正确,全部须要的资源是否可用

2.compile:编译项目源代码

3.test:使用合适的单元框架来测试已编译的源代码。

4.Package:把已编译的代码打包成可发布的格式,jar。

4)Package:把已编译的代码打包成可发布的格式,好比jar。

5)integration-test:若有须要,将包处理和发布到一个可以进行集成测试的环境。

6)verify:运行全部检查,验证包是否有效且达到质量标准。

7)install:把包安装到maven本地仓库,能够被其余工程做为依赖来使用。

8)Deploy:在集成或者发布环境下执行,将最终版本的包拷贝到远程的repository,使得其余的开发者或者工程能够共享。

3.

site生命周期:创建和发布项目站点,phase以下

1pre-site:生成项目站点以前须要完成的工做

2)site:生成项目站点文档

3)post-site:生成项目站点以后须要完成的工做

4)site-deploy:将项目站点发布到服务器

数据库索引

56. 什么是索引?

1)索引是对记录集多个字段进行排序的方法。

2)也是一个数据结构,在一张表中为一个字段建立索引,将建立另一个数据结构,包含字段的数值以及指向相关记录的指针,就能够对该数据结构进行二分法排序,当须要查询时就能够下降时间复杂度。

优点:快速存取数据;保证数据记录的惟一性;实现表和表之间的参照完整性;在使用order by group by子句进行数据的检索时,利用索引能够减小排序和分组的时间。

弊端:创建索引表也是会须要额外的空间。

57. 索引的工做原理:

在对表中记录进行搜索时并非对表中的数据进行所有的扫描遍历,而是查看在索引中定义的有序列,一旦在索引中找到了要查询的记录,就会获得一个指针,它会指向相应的表中数据所保存的位置。

58. 索引的类型:

1)汇集索引:数据页在物理上的有序的存储,数据页的物理顺序是按照汇集索引的顺序进行排列。在汇集索引中数据页汇集索引的叶子节点,数据页之间经过双向的链表形式相链接,实际的数据存储在叶节点中。

2)非汇集索引:叶子节点不存放具体的数据页信息,只存放索引的键值。非汇集索引的叶子节点包含着指向具体数据的指针,数据页之间没有链接,是相对独立的。

3)惟一索引:在整个表中仅仅会出现一次(主键约束/UNIQUE)

(4)非惟一索引:在提取数据时容许出现重复的值。

(5)单一索引和组合索引

59. 哪些状况下索引会失效?

1.条件中有or可是先后没有同时使用索引

2.多列索引,不是使用前面部分

3.like查询是以%开头

4.字符类型应该加单引号 防止转换为int类型

60. 数据库查询优化(Sql)

1应尽可能避免在 where 子句中使用!=或<>操做符,不然将引擎放弃使用索引而进行全表扫描。

2、对查询进行优化,应尽可能避免全表扫描,首先应考虑在 where order by 涉及的列上创建索引。

3、应尽可能避免在 where 子句中对字段进行 null 值判断,不然将致使引擎放弃使用索引而进行全表扫描,如:

     select id from t where num is null

能够在num上设置默认值0,确保表中num列没有null值,而后这样查询:

     select id from t where num=0

4、尽可能避免在 where 子句中使用 or 来链接条件,不然将致使引擎放弃使用索引而进行全表扫描,如:

     select id from t where num=10 or num=20

能够这样查询:

     select id from t where num=10

     union all

     select id from t where num=20

 五、下面的查询也将致使全表扫描:(不能前置百分号)

     select id from t where name like ‘�c%’

若要提升效率,能够考虑全文检索。

 六、in not in 也要慎用,不然会致使全表扫描,如:

     select id from t where num in(1,2,3)

对于连续的数值,能用 between 就不要用 in 了:

     select id from t where num between 1 and 3

 7、若是在 where 子句中使用参数,也会致使全表扫描。由于SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然 而,若是在编译时创建访问计划,变量的值仍是未知的,于是没法做为索引选择的输入项。以下面语句将进行全表扫描:

     select id from t where num=@num

能够改成强制查询使用索引:

     select id from t with(index(索引名)) where num=@num

 8、应尽可能避免在 where 子句中对字段进行表达式操做,这将致使引擎放弃使用索引而进行全表扫描。如:

     select id from t where num/2=100

应改成:

     select id from t where num=100*2

 九、应尽可能避免在where子句中对字段进行函数操做,这将致使引擎放弃使用索引而进行全表扫描。如:

     select id from t where substring(name,1,3)=’abc’–name以abc开头的id

     select id from t where datediff(day,createdate,’2005-11-30′)=0–’2005-11-30′生成的id

应改成:

     select id from t where name like ‘abc%’

     select id from t where createdate>=’2005-11-30′ and createdate<’2005-12-1′

 10、不要在 where 子句中的“=”左边进行函数、算术运算或其余表达式运算,不然系统将可能没法正确使用索引。

 11、在使用索引字段做为条件时,若是该索引是复合索引,那么必须使用到该索引中的第一个字段做为条件时才能保证系统使用该索引,不然该索引将不会被使 用,而且应尽量的让字段顺序与索引顺序相一致。

 十二、不要写一些没有意义的查询,如须要生成一个空表结构:

     select col1,col2 into #t from t where 1=0

这类代码不会返回任何结果集,可是会消耗系统资源的,应改为这样:

     create table #t(…)

 13、不少时候用 exists 代替 in 是一个好的选择:

     select num from a where num in(select num from b)

用下面的语句替换:

     select num from a where exists(select 1 from b where num=a.num)

 1四、并非全部索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段 sex,male、female几乎各一半,那么即便在sex上建了索引也对查询效率起不了做用。

 15、索引并非越多越好,索引当然能够提升相应的 select 的效率,但同时也下降了 insert update 的效率,由于 insert update 时有可能会重建索引,因此怎样建索引须要慎重考虑,视具体状况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有 必要。

 16.应尽量的避免更新 clustered 索引数据列,由于 clustered 索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将致使整个表记录的顺序的调整,会耗费至关大的资源。若应用系统须要频繁更新 clustered 索引数据列,那么须要考虑是否应将该索引建为 clustered 索引。

 17、尽可能使用数字型字段,若只含数值信息的字段尽可能不要设计为字符型,这会下降查询和链接的性能,并会增长存储开销。这是由于引擎在处理查询和链接时会 逐个比较字符串中每个字符,而对于数字型而言只须要比较一次就够了。

 18、尽量的使用 varchar/nvarchar 代替 char/nchar ,由于首先变长字段存储空间小,能够节省存储空间,其次对于查询来讲,在一个相对较小的字段内搜索效率显然要高些。

 19、任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。

 20、尽可能使用表变量来代替临时表。若是表变量包含大量数据,请注意索引很是有限(只有主键索引)。

 2一、避免频繁建立和删除临时表,以减小系统表资源的消耗。

 22、临时表并非不可以使用,适当地使用它们能够使某些例程更有效,例如,当须要重复引用大型表或经常使用表中的某个数据集时。可是,对于一次性事件,最好使 用导出表。

 23、在新建临时表时,若是一次性插入数据量很大,那么能够使用 select into 代替 create table,避免形成大量 log ,以提升速度;若是数据量不大,为了缓和系统表的资源,应先create table,而后insert。

 24、若是使用到了临时表,在存储过程的最后务必将全部的临时表显式删除,先 truncate table ,而后 drop table ,这样能够避免系统表的较长时间锁定。

 2五、尽可能避免使用游标,由于游标的效率较差,若是游标操做的数据超过1万行,那么就应该考虑改写。

 2六、使用基于游标的方法或临时表方法以前,应先寻找基于集的解决方案来解决问题,基于集的方法一般更有效。

 27、与临时表同样,游标并非不可以使用。对小型数据集使用 FAST_FORWARD 游标一般要优于其余逐行处理方法,尤为是在必须引用几个表才能得到所需的数据时。在结果集中包括“合计”的例程一般要比使用游标执行的速度快。若是开发时 间容许,基于游标的方法和基于集的方法均可以尝试一下,看哪种方法的效果更好。

 28、在全部的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每一个语句后向客户端发送 DONE_IN_PROC 消息。

 2九、尽可能避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。

 30、尽可能避免大事务操做,提升系统并发能力。查询sql语句中哪些比较慢

1.慢查询日志,通常设置查询超过两秒就记录

2.processlist:显示哪些线程正在运行.

3.explain关键字可让咱们更好的优化

61. 数据库设计优化:

1.反范式设计,尽可能是单表,能够高效利用索引

2.能够使用查询缓存,Mysql也会自带查询缓存

3.尽可能查询经过搜索引擎查不经过咱们

4.key,value数据库

62. 锁的优化策略

1.读写分离,锁分离

2.减小锁持有时间,能够减小其余的锁的持有时间

3.以正确的顺序得到和释放锁

4.适当的锁的范围扩大或者缩小,控制锁的粒度

63. Spring Bean中做用域

singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例。

prototype:原型模式,每次经过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例。

request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不一样的Bean实例。只有在Web应用中使用Spring时,该做用域才有效。

session:对于每次HTTP Session,使用session定义的Bean都将产生一个新实例。一样只有在Web应用中使用Spring时,该做用域才有效。

Globalsession:每一个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型状况下,仅在使用portlet context的时候有效。一样只有在Web应用中使用Spring时,该做用域才有效。

64. java中启定时任务

1.利用sleep特性//休眠

2.time和timerTask//定时器

3.ScheduledExecutorService service.scheduleAtFixedRate(runnable, 10, 1, TimeUnit.SECONDS);

 //任务调度服务

65. 操做系统如何进行分页调度

用户程序的地址空间被划分红若干固定大小的区域,称为“页”,相应地,内存空间分红若干个物理块,页和块的大小相等。可将用户程序的任一页放在内存的任一块中,实现了离散分配。

66. linux内核的三种主要调度策略:

1SCHED_OTHER 分时调度策略,

2,SCHED_FIFO实时调度策略,先到先服务

3,SCHED_RR实时调度策略,时间片轮转

67. TCPUDP相关

74.TCP经过什么方式提供可靠性:

1.超时重发,发出报文段要是没有收到及时的确认,会重发。

2.数据包的校验,也就是校验首部数据和。

3.对失序的数据从新排序

4.进行流量控制,防止缓冲区溢出

5.快重传和快恢复

6.TCP会将数据截断为合理的长度

68. TCPUDP的区别:

1.UDP是无链接的,TCP必须三次握手创建链接

2.UDP是面向报文,没有拥塞控制,因此速度快,适合多媒体通讯要求,好比及时聊天,支持一对一,一队多。多对一,多对多。

3.TCP只能是一对一的可靠性传输

TCP的RPC,在协议栈的下层,可以灵活的对字段进行定制,减小网络传输字节数,下降网络开销,提升性能,实现更大的吞吐量和并发数。可是实现代价高,底层复杂,难以获得开源社区的支持,难以实现跨平台

76.集群调优

1.load

load是被定义为特定时间间隔内运行队列中的平均线程数,uptime查看,通常load不大于3,咱们认为负载是正常的,若是每一个CPU的线程数大于5,表示负载就很是高了。

2.CPU利用率

查看cpu的消耗的状况命令:top | grep Cpu

查看磁盘的剩余空间命令:df -h

查看系统的内存的使用状况:free -m

69. 心跳检测方法

1.使用ping命令

对于full gc致使不响应,网络攻击这种 ping展现不明确

2.使用curl

访问咱们的自测地址

3.对不一样的功能使用curl检测,在response中加入状态头,表示正常

能够计算qps经过28原则

innodb存储引擎经过预写事务日志的方式保障事务的原子性,也就是在写入数据以前,先将数据操做写入日志,这种成为预写日志

轻量级锁认为在程序运行过程当中,绝大部分的锁,在整个同步周期内都是不存在竞争的,利用cas操做避免互斥开销。

偏向锁是jdk1.6中引入的一项优化,甚至能够省掉CAS操做,偏向锁偏向第一个得到他锁的线程,若是在接下来执行过程当中,这个锁没有被其余线程获取,则持有偏向锁的线程永远不须要同步。

70. GC调优

查看GC日志,根据GC日志来优化

咱们能够经过jps找到咱们虚拟机正在运行的进程。参数 经过jps -help了解。

Jstat -gc 或者 -gcutil 查看堆使用状况-class 配合Jps获得进程

BTrace原理利用hotspot虚拟中的热替换,把代码动态的替换到java程序内,可在不须要重启的时候就能够排除问题

JConsole

咱们也能够使用JConsole来分析这是一个图形化的,比较容易让咱们操做

使用VisualVM 进行远程链接 使用JMX方式,也有修改tomcat的catalina就好了

71. 内部类去访问外部变量,为何须要加final?

题目有点问题,并非全部的外部变量才加final,咱们的内部类访问咱们的成员变量就不须要加final,可是访问局部变量就必需要加final,由于方法(main方法)结束咱们栈帧也就销毁了,可是咱们内部类在堆中并无被销毁,若是引用了成员变量,这时候被销毁了确定是不行的,因此咱们就须要成员变量设置为final,让其在方法(main方法)结束时不会被销毁。

72. 泛型

泛型的做用:在咱们没有泛型的时候,咱们经过对Object的引用来对参数的任意化,任意化有个缺点就是要作显示的强制类型转换,强制转换有一个很差的地方是运行的时候才会报错,泛型的好处实在编译的时候检查类型安全,因此泛型的特色就是简单安全,泛型的原理是类型擦除,java的泛型是伪泛型,在编译期间,全部的泛型信息都会被擦除掉。在生成的java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会在编译器编译的时候去掉。好比List

73. nginxapache的对比

1.nginx相对于apache来讲

(1轻量级占用的内存少;

(2)抗并发,nginx是异步非阻塞,apache是阻塞的,在高并发的状况下,nginx的性能优;

(3)高度模块化的设计,编写模块相对简单;

(4)社区活跃,各类高性能模块有。

适合场景:apache适合于动态的请求,而负载均衡和静态请求适合nginx,nginx采用的是epoll,而且有本身的一套sendfile系统,减小在内存中的赋值次数。

2.apache 相对于nginx 的优势:

(1)rewrite ,比nginx 的rewrite 强大

(2)模块超多,基本想到的均可以找到;

(3)少bug ,nginx 的bug 相对较多

(4)超稳定。

74. 线程、进程共享和独立

共享的部分:

1.进程代码段

2.进程的公有数据(利用这些共享的数据,线程很容易的实现相互之间的通信)

3.进程打开的文件描述符、

4.信号的处理器、

5.进程的当前目录

6.进程用户ID与进程组ID

线程独有的内容包括:

1.线程ID

2.寄存器组的值

3.线程的堆栈

4.错误返回码

5.线程的信号屏蔽码

最大的优点就是线程极高的执行效率。由于子程序切换不是线程切换,而是由程序自身控制,所以,没有线程切换的开销,和多线程比,线程数量越多,线程的性能优点就越明显。

第二大优点就是不须要多线程的锁机制,由于只有一个线程,也不存在同时写变量冲突,在线程中控制共享资源不加锁,只须要判断状态就行了,因此执行效率比多线程高不少。

75. 简单的说一下nginx的优势

1.做为高性能的web服务器:相比Apache,Nginx使用更少的资源,支持更多的并发链接,体现更高的效率,这点让Nginx受到虚拟主机提供商的欢迎。一个Nginx实例可以轻松支持高达5万并发。

2.做为负载均衡服务器:Nginx即能够在内部直接支持PHP,也能够支持做为HTTP代理服务器对外进行服务,独有的send files系统,减小文件复制次数

3.做为邮件代理服务器:也比Apache好不少。

4.Nginx安装简单,配置文件很是简洁。启动容易,7*24小时几乎不间断,能够进行热更新。

76. BIO

在BIO中读和写都是同步阻塞的,阻塞的时间取决于对方I/O线程的处理速度和网络的传输速度。本质上来说,咱们是没法保证生产环境的网络情况和对端的应用程序能够足够快,应用程序是不该该依赖对方的处理速度,它的可靠性就很是差。BIO就算用线程池实现,要是全部可用线程都被阻塞到故障点中,后续的全部I/O消息都将在队列中排队。

77. NIO

1)提供了高速,面向块的I/O

2)在NIO中全部数据都是用缓冲区来处理的,也就是使用咱们的jvm中的direct memory(直接内存)。缓冲区是一个数组,可是缓冲区不只仅是一个数组,缓冲区提供了对数据的结构化访问以及维护读写位置等信息。

3)在NIO中channel(通道)也是特别重要的他是咱们数据读写的通道,通常来讲流好比inputStream和outputStream都是单向的,而通道是双向的,是全双工的

4)多路复用器Selector也是比较重要的,掌握它对于咱们的NIO编程来讲是比较重要的。多路复用器提供选择已经就绪的任务的能力。Selector会不断轮训注册在其上的Channel,若是某个Channel上面发生读或者写事件,这个Channel就处于就绪状态,会被Selector轮询出来,经过SelectionKey能够获取就绪Channel的集合,进行后续的I/o操做。咱们只须要一个线程就能够管理咱们多个客户端。

78. 垃圾收集器

1.Serial收集器

    Serial收集器是JAVA虚拟机中最基本、历史最悠久的收集器,在JDK 1.3.1以前是JAVA虚拟机新生代收集的惟一选择。Serial收集器是一个单线程的收集器,但它的“单线程”的意义并不只仅是说明它只会使用一个 CPU或一条收集线程去完成垃圾收集工做,更重要的是在它进行垃圾收集时,必须暂停其余全部的工做线程,直到它收集结束。

     Serial收集器到JDK1.7为止,它依然是JAVA虚拟机运行在Client模式下的默认新生代收集器。它也有着优于其余收集器的地方:简单而高 效(与其余收集器的单线程比),对于限定单个CPU的环境来讲,Serial收集器因为没有线程交互的开销,专心作垃圾收集天然能够得到最高的单线程收集 效率。在用户的桌面应用场景中,分配给虚拟机管理的内存通常来讲不会很大,收集几十兆甚至一两百兆的新生代(仅仅是新生代使用的内存,桌面应用基本上不会 再大了),停顿时间彻底能够控制在几十毫秒最多一百多毫秒之内,只要不是频繁发生,这点停顿是能够接受的。因此,Serial收集器对于运行在 Client模式下的虚拟机来讲是一个很好的选择。

2. Parallel(并行)收集器

这是 JVM 的缺省收集器。就像它的名字,其最大的优势是使用多个线程来经过扫描并压缩堆。串行收集器在GC时会中止其余全部工做线程(stop-the- world),CPU利用率是最高的,因此适用于要求高吞吐量(throughput)的应用,但停顿时间(pause time)会比较长,因此对web应用来讲就不适合,由于这意味着用户等待时间会加长。而并行收集器能够理解是多线程串行收集,在串行收集基础上采用多线 程方式进行GC,很好的弥补了串行收集的不足,能够大幅缩短停顿时间(以下图表示的停顿时长高度,并发比并行要短),所以对于空间不大的区域(如 young generation),采用并行收集器停顿时间很短,回收效率高,适合高频率执行。

3.CMS收集器

    CMS(Concurrent Mark Sweep)收集器是基于“标记-清除”算法实现的,它使用多线程的算法去扫描堆(标记)并对发现的未使用的对象进行回收(清除)。整个过程分为6个步骤,包括:

初始标记(CMS initial mark)

并发标记(CMS concurrent mark)

并发预清理(CMS-concurrent-preclean)

从新标记(CMS remark)

并发清除(CMS concurrent sweep)

并发重置(CMS-concurrent-reset)

其中初始标记、从新标记这两个步骤仍然须要“Stop The World”。初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,并发标记阶段就是进行GC Roots Tracing的过程,而从新标记阶段则是为了修正并发标记期间,因用户程序继续运做而致使标记产生变更的那一部分对象的标记记录,这个阶段的停顿时间一 般会比初始标记阶段稍长一些,但远比并发标记的时间短。其余动做都是并发的。

须要注意的是,CMS收集器没法处理浮动垃圾(Floating Garbage),可能出现“Concurrent Mode Failure”失败而致使另外一次Full GC的产生。因为CMS并发清理阶段用户线程还在运行着,伴随程序的运行天然还会有新的垃圾不断产生,这一部分垃圾出如今标记过程以后,CMS没法在本次 收集中处理掉它们,只好留待下一次GC时再将其清理掉。这一部分垃圾就称为“浮动垃圾”。也是因为在垃圾收集阶段用户线程还须要运行,即还须要预留足够的 内存空间给用户线程使用,所以CMS收集器不能像其余收集器那样等到老年代几乎彻底被填满了再进行收集,须要预留一部分空间提供并发收集时的程序运做使 用。在默认设置下,CMS收集器在老年代使用了68%的空间后就会被激活,这是一个偏保守的设置,若是在应用中老年代增加不是太快,能够适当调高参数 -XX:CMSInitiatingOccupancyFraction的值来提升触发百分比,以便下降内存回收次数以获取更好的性能。要是CMS运行期 间预留的内存没法知足程序须要,就会出现一次“Concurrent Mode Failure”失败,这时候虚拟机将启动后备预案:临时启用Serial Old收集器来从新进行老年代的垃圾收集,这样停顿时间就很长了。因此说参数-XX:CMSInitiatingOccupancyFraction设置 得过高将会很容易致使大量“Concurrent Mode Failure”失败,性能反而下降。

try catch有return 在字节码中 能够看到会出现Goto跳转行数,跳转到finally中的return

79. Tomcat总结构

最外层的Server提供接口访问内部的Service服务。

Service服务的做用就是把Connector 在Connetor中监听端口和Container链接起来,方便咱们的操纵控制。

在tomcat中生命周期是统一的由Lifecycle来管理的

在lifecycle中有两个方法比较重要start和stop,调用server的start会去调用本身下面全部service的start方法

Connector最重要的功能就是接受链接请求而后分配线程处理

在Container 4个级别Engine,Host,Context,warpper,这四个组件不是平行的,而是父子关系,Engine 包含 Host,Host 包含 Context,Context 包含 Wrapper。一般一个 Servlet class 对应一个 Wrapper,若是有多个 Servlet 就能够定义多个 Wrapper,若是有多个 Wrapper 就要定义一个更高的 Container 了,如 Context。在Host中有个value比较重要,相似于一个管道,和拦截器链差很少,咱们在中间能够进行一些处理。

Engine中只能添加子容器Host,不能添加父容器.Engine下能够配置多个虚拟主机Virtual Host,每一个虚拟主机都有一个域名

当Engine得到一个请求时,它把该请求匹配到某个Host上,而后把该请求交给该Host来处理Engine有一个默认虚拟主机,当请求没法匹配到任何一个Host上的时候,将交给该默认Host来处理

一个Host就相似于一个虚拟主机,用来管理应用。表明一个Virtual Host,虚拟主机,每一个虚拟主机和某个网络域名Domain Name相匹配

每一个虚拟主机下均可以部署(deploy)一个或者多个Web App,每一个Web App对应于一个Context,有一个Context path

当Host得到一个请求时,将把该请求匹配到某个Context上,而后把该请求交给该Context来处理

匹配的方法是“最长匹配”,因此一个path==""的Context将成为该Host的默认Context

全部没法和其它Context的路径名匹配的请求都将最终和该默认Context匹配。

Context 表明 Servlet 的 Context,它具有了 Servlet 运行的基本环境,理论上只要有 Context 就能运行 Servlet 了。简单的 Tomcat 能够没有 Engine 和 Host。

Context 最重要的功能就是管理它里面的 Servlet 实例,Servlet 实例在 Context 中是以 Wrapper 出现的,还有一点就是 Context 如何才能找到正确的 Servlet 来执行它呢?

一个Context对应于一个Web Application,一个Web Application由一个或者多个Servlet组成

Context在建立的时候将根据配置文件" role="presentation" style='font-size:14px;font-style:normal;font-weight:normal;color:rgb(0, 0, 0);'>CATALINAHOME/conf/web.xml和WEBAPP_HOME/WEB-INF/web.xml载入Servlet类

当Context得到请求时,将在本身的映射表(mapping table)中寻找相匹配的Servlet类

若是找到,则执行该类,得到请求的回应,并返回.

80. 线程池参数

JDK1.5中引入了强大的concurrent包,其中最经常使用的莫过了线程池的实现。ThreadPoolExecutor(线程池执行器),它给咱们带来了极大的方便,但同时,对于该线程池不恰当的设置也可能使其效率并不能达到预期的效果,甚至仅至关于或低于单线程的效率。

ThreadPoolExecutor类可设置的参数主要有:

(1)corePoolSize  基本大小

核心线程数,核心线程会一直存活,即便没有任务须要处理。当线程数小于核心线程数时,即便现有的线程空闲,线程池也会优先建立新线程来处理任务,而不是直接交给现有的线程处理。

核心线程在allowCoreThreadTimeout被设置为true时会超时退出,默认状况下不会退出。

(2)maxPoolSize  最大大小

当线程数大于或等于核心线程corePoolSize,且任务队列已满时,线程池会建立新的线程,直到线程数量达到maxPoolSize。若是线程数已等于maxPoolSize,且任务队列已满,则已超出线程池的处理能力,线程池会拒绝处理任务而抛出异常。

 keepAliveTime  大于coolPoolSize 会退出

当线程空闲时间达到keepAliveTime,该线程会退出,直到线程数量等于corePoolSize。若是allowCoreThreadTimeout设置为true,则全部线程均会退出直到线程数量为0。

 allowCoreThreadTimeout  是否退出核心线程

是否容许核心线程空闲退出,默认值为false。

 queueCapacity

任务队列容量。从maxPoolSize的描述上能够看出,任务队列的容量会影响到线程的变化,所以任务队列的长度也须要恰当的设置。

81. 线程池按如下行为执行任务

当线程数小于核心线程数时,建立线程。

当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列。

当线程数大于等于核心线程数,且任务队列已满

若线程数小于最大线程数,建立线程

若线程数等于最大线程数,抛出异常,拒绝任务

系统负载

参数的设置跟系统的负载有直接的关系,下面为系统负载的相关参数:

 tasks,每秒须要处理的最大任务数量

 tasktime,处理每一个任务所须要的时间

 responsetime,系统容许任务最大的响应时间,好比每一个任务的响应时间不得超过2秒。

参数设置

corePoolSize:

每一个任务须要tasktime秒处理,则每一个线程每钞可处理 1/tasktime个任务。系统每秒有tasks个任务须要处理,则须要的线程数为:tasks/(1/tasktime),即 tasks*tasktime个线程数。假设系统每秒任务数为100~1000,每一个任务耗时0.1秒,则须要100*0.1至1000*0.1,即 10~100个线程。那么corePoolSize应该设置为大于10,具体数字最好根据8020原则,即80%状况下系统每秒任务数,若系统80%的情 况下第秒任务数小于200,最多时为1000,则corePoolSize可设置为20。

queueCapacity:

任务队列的长度要根据核心线程数,以及系统对任务响应时间的要求有关。队列长度能够设置为(corePoolSize/tasktime)*responsetime (20/0.1)*2=400,即队列长度可设置为400。

队列长度设置过大,会致使任务响应时间过长,切忌如下写法:

LinkedBlockingQueue queue = new LinkedBlockingQueue();

这其实是将队列长度设置为Integer.MAX_VALUE,将会致使线程数量永远为corePoolSize,不再会增长,当任务数量陡增时,任务响应时间也将随之陡增。

maxPoolSize:

当系统负载达到最大值时,核心线程数已没法按时处理完全部任务,这时就须要增长线程。每秒200个任务须要20个线程,那么当每秒达到1000个任务时,则须要(1000-queueCapacity)* (20/200),即60个线程,可将maxPoolSize设置为60。

keepAliveTime:

线程数量只增长不减小也不行。当负载下降时,可减小线程数量,若是一个线程空闲时间达到keepAliveTiime,该线程就退出。默认状况下线程池最少会保持corePoolSize个线程。

allowCoreThreadTimeout:

默认状况下核心线程不会退出,可经过将该参数设置为true,让核心线程也退出。

以上关于线程数量的计算并无考虑CPU的状况。若结合CPU的状况,好比,当线程数量达到50时,CPU达到100%,则将 maxPoolSize设置为60也不合适,此时若系统负载长时间维持在每秒1000个任务,则超出线程池处理能力,应设法下降每一个任务的处理时间 (tasktime)。

使用ThreadLocal解决SimpleDateFormat,

privatestatic ThreadLocal threadLocal = new ThreadLocal() {        @Override        protected DateFormat initialValue() {            returnnew SimpleDateFormat("yyyy-MM-dd HH:mm:ss");        }    };

或者推荐Joda-Time处理时间比较推荐

在java线程中有6个状态也就是Thread中的枚举类

NEW,RUNNABLE,WAITING,TIME_WAITING,BLOCKED,TERMINATED

应该在try{} catch{}中从新设置中断状态,由于发出中断异常被退出了。

82. java内存模型

jvm规范定了jvm内存模型来屏蔽掉各类操做系统,虚拟机实现厂商和硬件的内存访问差别,确保java程序在全部操做系统和平台上可以实现一次编写,处处运行的效果。

83. 为何IP协议也可以进行数据的不可靠传输,还须要Udp

1.咱们须要端口号来实现应用程序间的区分

2.UDP校验和能够实现传输层的校验,虽然UDP协议不具有纠错能力,可是能够对出错的数据包进行丢弃,而IP的校验只是在校验IP报头,而不是整个数据包,整个数据包的校验是在传输层完成的,若是出错了,就会把出错的数据包丢弃。这也就是为何须要有传输层

84. 进程通讯中管道和共享内存谁的速度快?

1.管道通讯方式的中间介质是文件,一般称这种文件为管道文件。两个进程利用管道进行通讯,一个进程为写进程,另外一个进程为读进程。写进程经过往管道文件中写入信息,读进程经过读端从管道文件中读取信息,这样的方式进行通讯。

2.共享内存是最快的可用IPC形式,他经过把共享的内存空间映射到进程的地址空间,进程间的数据传递不在经过执行任何进入内核的系统调用,节约了时间。java内存模型就采用的是共享内存的方式。各个进程经过公共的内存区域进行通讯。

85. java线程池shutdownshutdownNow的区别?

Shutdown()方法

当线程池调用该方法时,线程池的状态则马上变成SHUTDOWN状态。此时,则不能再往线程池中添加任何任务,不然将会抛出RejectedExecutionException(拒绝执行异常)异常。可是,此时线程池不会马上退出,直到添加到线程池中的任务都已经处理完成,才会退出。

shutdownNow()方法

根据JDK文档描述,大体意思是:执行该方法,线程池的状态马上变成STOP状态并试图中止全部正在执行的线程,再也不处理还在池队列中等待的任务,固然,它会返回那些未执行的任务。

它试图终止线程的方法是经过调用Thread.interrupt()方法来实现的,可是你们知道,这种方法的做用有限,若是线程中没有sleep 、wait、Condition、定时锁等应用, interrupt()方法是没法中断当前的线程的。因此,ShutdownNow()并不表明线程池就必定当即就能退出,它可能必需要等待全部正在执行的任务都执行完成了才能退出。

86. Integer的装箱和拆箱的基本原理

Integer包装类是Java最基本的语法糖优化,若是咱们写一段程序,经过反编译就会看到,经过的是Integer.valueOf()或者Interger.intValue()来进行转换的。

Integer和int比较会自动拆箱,

当Integer和integer比较的时候是不会自动拆箱的,除非遇到了算术符,才会调用intValue()方法去拆箱。而且在Integer中的equals是不会处理数据类型转换关系的,使用时是须要慎用,在equals方法中判断为Integer类的才会执行真正的判断流程也就是拆箱去判断,因此不会处理数据类型转换好比Long。若是是基本类型比较,编译器会隐形的把int转换为long,就能够得出正确的结论。

87. 为何不推荐使用resumesuspend

由于在使用suspend()去挂起线程的时候,suspend在致使线程暂停的同时,不会去释听任何锁的资源。必需要等待resume()操做,被挂起的线程才能继续。若是咱们resume()操做意外地在suspend()前就执行了,那么被挂起的线程可能很难有机会被继续执行。而且,更严重的是:所占用的锁不会被释放,所以可能会致使整个系统工做不正常

yield是谦让,调用后会使当前线程让出CPU,可是注意的地方让出CPU并不表示当前线程不执行了。当前线程在让出CPU后,还会进行CPU资源的争夺,有可能刚刚一让立刻又进。

88. 数据库事务的隔离级别

1.未提交读 都不能解决

2.已提交读 能解决脏读

3.可重复读 能解决脏读,不可重复读

4.序列化读 能解决脏读,不可重复读,幻读

89. Docker和虚拟机的比较

1.传统的虚拟机在宿主机操做系统上面会利用虚拟机管理程序去模拟完整的一个虚拟机操做系统,docker只是在操做系统上的虚拟化,直接复用本地主机的操做系统,很是轻量级。

docker启动速度通常在秒级,虚拟机启动速度通常在分钟级。

2.对于资源的使用通常是mb,一台机器能够有上千个docker容器,可是虚拟机占用资源为GB,只能支持几个。

3.性能:接近原生,因为又虚拟化了一层因此效率低。

4.docker采用相似git的命令学习升本低,指令简单。

5.虚拟机隔离性是彻底隔离,容器是安全隔离

90. lucence组件

每个词都会有一个倒排表,多个能够合并

为了标识webSocket:会在请求头中写一个upgrade:webSocket

HTTP比较

一样做为应用层的协议,WebSocket在现代的软件开发中被愈来愈多的实践,和HTTP有不少类似的地方,这里将它们简单的作一个纯我的、非权威的比较:

相同点

都是基于TCP的应用层协议。

都使用Request/Response模型进行链接的创建。

在链接的创建过程当中对错误的处理方式相同,在这个阶段WS可能返回和HTTP相同的返回码。

均可以在网络中传输数据。

不一样点

 WS使用HTTP来创建链接,可是定义了一系列新的header域,这些域在HTTP中并不会使用。

 WS的链接不能经过中间人来转发,它必须是一个直接链接。

 WS链接创建以后,通讯双方均可以在任什么时候刻向另外一方发送数据。f

 WS链接创建以后,数据的传输使用帧来传递,再也不须要Request消息。

 WS的数据帧有序。

91. 微服务架构

首先看一下微服务架构的定义:微服务(MSA)是一种架构风格,旨在经过将功能分解到各个离散的服务中以实现对解决方案的解耦。它有以下几个特征:

小,且只干一件事情。

独立部署和生命周期管理。

异构性

轻量级通讯,RPC或者Restful。

92. BIO通讯模型图:

BIO以是一客户端一线程,一个Acceptor线程来接受请求,以后为每个客户端都建立一个新的线程进行链路处理,最大的问题缺少弹性伸缩能力,客户端并发访问量增长后,线程数急剧膨胀。能够用线程池缓解可是仍是不行。

NIO非阻塞IO解决了这个问题,一个线程就能够管理多个Socket.

在NIO中有三个须要咱们了解Buffer,Channel,Selector

Buffer:NIO是面向缓冲区,IO是面向流的。缓冲区实质上一个数组

,缓冲区不只仅是一个数组,缓冲区提供了对数据结构化访问以及维护读写位置等信息。

通道Channel:

Channel是一个通道,网络数据经过Channel读取和写入。通道与流的不一样之处在于通道是双向的,流是一个方向上移动,通道能够用于读写操做,特别是在UNIX网络编程模型底层操做系统的通道都是全双工的,同时支持读写操做。

Selector:多路复用器NIo编程的基础,多路复用器提供选择就绪任务的 能力。简单来讲Selector会不断注册在其上的Channel,若是某个Channel上面发生读或者写时间,这个Channel就处于就绪状态,会被Selector轮询出来,经过SelectionKey,一个多路复用器能够同时轮询多个Channel,JDK使用了epoll代理传统select实现,因此没有最大链接句柄fd的限制,意味着一个线程负责Selector的轮询,就能够接入成千上万的客户端

select/poll epoll select poll顺序扫描fd,就绪就返回fd。epoll则是 采用事件驱动,用回调的方式返回fd。

93. 面向对象设计七大原则

1. 单一职责原则(Single Responsibility Principle

每个类应该专一于作一件事情。

2. 里氏替换原则(Liskov Substitution Principle

超类存在的地方,子类是能够替换的。

3. 依赖倒置原则(Dependence Inversion Principle

实现尽可能依赖抽象,不依赖具体实现。

4. 接口隔离原则(Interface Segregation Principle

应当为客户端提供尽量小的单独的接口,而不是提供大的总的接口。

5. 迪米特法则(Law Of Demeter

又叫最少知识原则,一个软件实体应当尽量少的与其余实体发生相互做用。

6. 开闭原则(Open Close Principle

面向扩展开放,面向修改关闭。

7. 组合/聚合复用原则(Composite/Aggregate Reuse Principle CARP

尽可能使用合成/聚合达到复用,尽可能少用继承。原则: 一个类中有另外一个类的对象。

94. 拦截器和过滤器的区别

强类型:不容许隐形转换

弱类型:容许隐形转换

静态类型:编译的时候就知道每个变量的类型,由于类型错误而不能作的事情是语法错误.

动态类型:编译得时候不知道每个变量的类型,由于类型错误而不能作的事情是运行时错误

编译语言和解释语言:解释性编程语言,每一个语句都是执行的时候才翻译并且是一句一句的翻译就很低。

编译的语言就只须要一次就能够了

95. 继承Thread 接口Runnabel的区别

主要是继承和实现接口的两个区别,若是只想重写run方法就能够使用,若是不重写其余方法 就使用runnable,若是使用实现接口的实现,让本身方便管理线程以及让线程复用,能够使用线程池去建立。

96. hash算法(特色、哈希函数构造、解决冲突的策略)

哈希表的概念:

哈希表就是一种以键-值(key-indexed) 存储数据的结构,咱们只要输入待查找的值即key,便可查找到其对应的值。

哈希表的实现思路:

若是全部的键都是整数,那么就能够使用一个简单的无序数组来实现:将键做为索引,值即为其对应的值,这样就能够快速访问任意键的值。这是对于简单的键的状况,咱们将其扩展到能够处理更加复杂的类型的键。对于冲突的状况,则须要处理地址的冲突问题。因此,一方面要构造出良好的哈希函数,对键值集合进行哈希,另一方面须要设计出良好的解决冲突的算法,处理哈希碰撞的冲突。

哈希表的查找步骤:

(1)使用哈希函数将被查找的键转换为数组的索引。在理想的状况下,不一样的键会被转换为不一样的索引值,可是在有些状况下咱们须要处理多个键被哈希到同一个索引值的状况。因此哈希查找的第二个步骤就是处理冲突

(2)处理哈希碰撞冲突。有不少处理哈希碰撞冲突的方法,本文后面会介绍拉链法线性探测法

哈希表的思想:

是一个在时间和空间上作出权衡的经典例子。若是没有内存限制,那么能够直接将键做为数组的索引。那么全部的查找时间复杂度为O(1);若是没有时间限制,那么咱们能够使用无序数组并进行顺序查找,这样只须要不多的内存。哈希表使用了适度的时间和空间来在这两个极端之间找到了平衡。只须要调整哈希函数算法便可在时间和空间上作出取舍。

哈希表的工做步骤:

 1)   哈希(Hash)函数是一个映象,即将关键字的集合映射到某个地址集合上,它的设置很灵活,只要这个地址集合的大小不超出容许范围便可;

 2)  因为哈希函数是一个压缩映象,所以,在通常状况下,很容易产生“冲突”现象,即: key1!=key2,而  f  (key1) = f(key2)。键不一样,可是对应的取值相同。

3).  只能尽可能减小冲突而不能彻底避免冲突,这是由于一般关键字集合比较大,其元素包括全部可能的关键字,而地址集合的元素仅为哈希表中的地址值。

哈希函数的构造方法:

一、直接地址法

以数据元素的关键字k自己或者他的线性的函数做为它 的哈希地址,也就是H(k)=k,或者H(k)=a*k+b;

适用的场景:地址集合的大小==关键字的集合。

二、数字分析法

取数据元素关键字中某些取值较均匀的数字位做为哈希地址的方法

适用的场景:能预先估计出全体关键字的每一位上各类数字出现的频度。

三、折叠法

将关键字分割成位数相同的几部分(最后一部分的位数能够不一样),而后取这几部分的叠加和(舍去进位),这方法称为折叠法

适用场景:关键字的数字位数特别多。

四、平方取中法

先取关键字的平方,而后根据可以使用空间的大小,选取平方数是中间几位为哈希地址。

适用场景:经过取平方扩大差异,平方值的中间几位和这个数的每一位都相关,则对不一样的关键字获得的哈希函数值不易产生冲突,由此产生的哈希地址也较为均匀。

五、减去法

六、基数转换法

七、除留余数法

八、随机数法

九、随机乘数法

十、旋转法

构造哈希哈希函数的原则:

一、计算哈希函数的时间

二、关键子的长度

三、哈希表的长度

四、关键字的分布的状况

五、记录查找频率

哈希函数的冲突解决的方法:

一、开放地址法

这种方法也称再散列法,其基本思想是:当关键字key的哈希地址p=H(key)出现冲突时,以p为基础,产生另外一个哈希地址p1,若是p1仍然冲突,再以p为基础,产生另外一个哈希地址p2,…,直到找出一个不冲突的哈希地址pi ,将相应元素存入其中。这种方法有一个通用的再散列函数形式:

          Hi=(H(key)+di)% m   i=1,2,…,n

其中H(key)为哈希函数,m 为表长,di称为增量序列。增量序列的取值方式不一样,相应的再散列方式也不一样。主要有如下三种:

l         线性探测再散列

    dii=1,2,3,…,m-1

这种方法的特色是:冲突发生时,顺序查看表中下一单元,直到找出一个空单元或查遍全表。

l         二次探测再散列

    di=12,-12,22,-22,…,k2,-k2    ( k<=m/2 )

这种方法的特色是:冲突发生时,在表的左右进行跳跃式探测,比较灵活。

l        伪随机探测再散列

    di=伪随机数序列。

二、再哈希法

这种方法是同时构造多个不一样的哈希函数:

    Hi=RH1(key)  i=1,2,…,k

当哈希地址Hi=RH1(key)发生冲突时,再计算Hi=RH2(key)……,直到冲突再也不产生。这种方法不易产生汇集,但增长了计算时间。

三、链地址法

这种方法的基本思想是将全部哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,于是查找、插入和删除主要在同义词链中进行。链地址法适用于常常进行插入和删除的状况。

四、创建公共溢出区

这种方法的基本思想是:将哈希表分为基本表溢出表两部分,凡是和基本表发生冲突的元素,一概填入溢出表

97. 类加载的方式

1.经过new

2.经过反射利用当前线程的classloader

3.本身继承实现一个classloader实现本身的类装载器

class.forName Classloader.loadClass区别

Classloader

104.HashMap内部是怎么实现的?(拉链式结构)

98. 核心:hashMap采用拉链法,构成“链表的数组”

存储示意图:

99. 索引index创建规则:

1)通常状况下经过hash(key)%length实现,元素存储在数组中的索引是由key的哈希值对数组的长度取模获得。

2)hashmap也是一个线性的数组实现的,里面定义一个内部类Entry,属性包括key、value、next.Hashmap的基础就是一个线性数组,该数组为Entry[] ,map里面的内容都保存在entry[]数组中。

(3)肯定数组的index:hashcode%table.length

数组的下标index相同,可是不表示hashcode相同。

实现随机存储的方法:

// 存储时:

int hash = key.hashCode(); // 这个hashCode方法这里不详述,只要理解每一个key的hash是一个固定的int值

int index = hash % Entry[].length;

Entry[index] = value;

 

// 取值时:

int hash = key.hashCode();

int index = hash % Entry[].length;

return Entry[index];

put方法的实现:

若是两个key经过hash%Entry[].length获得的index相同,会不会有覆盖的危险?

这里HashMap里面用到链式数据结构的一个概念。上面咱们提到过Entry类里面有一个next属性,做用是指向下一个Entry。打个比方, 第一个键值对A进来,经过计算其key的hash获得的index=0,记作:Entry[0] = A。一会后又进来一个键值对B,经过计算其index也等于0,如今怎么办?HashMap会这样作:B.next = A,Entry[0] = B,若是又进来C,index也等于0,那么C.next = B,Entry[0] = C;这样咱们发现index=0的地方其实存取了A,B,C三个键值对,他们经过next这个属性连接在一块儿。因此疑问不用担忧。也就是说数组中存储的是最后插入的元素

get方法的实现:

先定位到数组元素,再遍历该元素处的链表

table的大小:

table的初始的大小并非initialCapacity,是initialCapacity的2的n次幂

目的在于:当哈希表的容量超过默认的容量时,必须从新调整table的大小,当容量已经达到最大的可能的值时,这时须要建立一张新的表,将原来的表映射到该新表。

req.getSession().invalidate(); 销毁session

req.getSession().setMaxInactiveInterval(30); 设置默认session的过时时间,tomcat的默认过时时间是 30分钟

100. 利用线程池的优点:

1下降资源消耗。经过重复利用已建立的线程下降线程建立和销毁形成的消耗。

二、提升响应速度。当任务到达时,任务能够不须要等到线程建立就能当即执行。

三、提升线程的可管理性。线程是稀缺资源,若是无限制的建立,不只会消耗系统资源,还会下降系统的稳定性,使用线程池能够进行统一的分配,调优和监控。

boolean 单独使用的时候还会被变成int,4个字节

boolean[] 数组使用的时候变成byte,1个字节

101. CacheBuffer的区别

Cache:缓存区,位于cpu和主内存之间容量很小但速度很快的存储器,由于CPU的速度远远高于主内存的速度,CPU从内存中读取数据许要等待很长的时间,而Cache保存着CPU刚用过的数据或循环使用的部分数据,Cache读取数据更快,减小cpu等待时间。

Buffer:缓冲区,用于存储速度不一样步的状况,处理系统两端速度平衡,为了减少短时间内突发I/O的影响,起到流量整形的做用。速度慢的能够先把数据放到buffer,而后达到必定程度在读取数据

内链接:

必须两个表互相匹配才会出现

外连接

左外连接:左边不加限制

右外链接:右边不加限制

全链接:左右都不加限制

102. 如何建立索引

全文检索的索引建立过程通常有如下几步:

第一步:一些要索引的原文档(Document)

为了方便说明索引建立过程,这里特地用两个文件为例:

文件一:Students should be allowed to go out with their friends, but not allowed to drink beer.

文件二:My friend Jerry went to school to see his students but found them drunk which is not allowed.

第二步:将原文档传给分词器(Tokenizer)

分词器(Tokenizer)会作如下几件事情(此过程称为Tokenize)

1. 将文档分红一个一个单独的单词。

2. 去除标点符号。

3. 去除停词(Stop word)

所谓停词(Stop word)就是一种语言中最普通的一些单词,因为没有特别的意义,于是大多数状况下不能成为搜索的关键词,于是建立索引时,这种词会被去掉而减小索引的大小。

英语中停词(Stop word)如:“the”,“a”,“this”等。

对于每一种语言的分词组件(Tokenizer),都有一个停词(stop word)集合。

通过分词(Tokenizer)后获得的结果称为词元(Token)

在咱们的例子中,便获得如下词元(Token):

“Students”,“allowed”,“go”,“their”,“friends”,“allowed”,“drink”,“beer”,“My”,“friend”,“Jerry”,“went”,“school”,“see”,“his”,“students”,“found”,“them”,“drunk”,“allowed”。

第三步:将获得的词元(Token)传给语言处理组件(Linguistic Processor)

语言处理组件(linguistic processor)主要是对获得的词元(Token)作一些同语言相关的处理。

对于英语,语言处理组件(Linguistic Processor)通常作如下几点:

1. 变为小写(Lowercase)

2. 将单词缩减为词根形式,如“cars”“car”等。这种操做称为:stemming

3. 将单词转变为词根形式,如“drove”“drive”等。这种操做称为:lemmatization

并且在此过程当中,咱们惊喜地发现,搜索“drive”,“driving”,“drove”,“driven”也可以被搜到。由于在咱们的索引 中,“driving”,“drove”,“driven”都会通过语言处理而变成“drive”,在搜索时,若是您输入“driving”,输入的查询 语句一样通过咱们这里的一到三步,从而变为查询“drive”,从而能够搜索到想要的文档。

ZK实现分布式锁- 是否存在,而且最小的

根据ZK中节点是否存在,能够做为分布式锁的锁状态,以此来实现一个分布式锁,下面是分布式锁的基本逻辑:

客户端调用create()方法建立名为“/dlm-locks/lockname/lock-”的临时顺序节点。

客户端调用getChildren(“lockname”)方法来获取全部已经建立的子节点。

客户端获取到全部子节点path以后,若是发现本身在步骤1中建立的节点是全部节点中序号最小的,那么就认为这个客户端得到了锁。

若是建立的节点不是全部节点中须要最小的,那么则监视比本身建立节点的序列号小的最大的节点,进入等待。直到下次监视的子节点变动的时候,再进行子节点的获取,判断是否获取锁。

并且zk的临时节点能够直接避免网络断开或主机宕机,锁状态没法清除的问题,顺序节点能够避免惊群效应。这些特性都使得利用ZK实现分布式锁成为了最广泛的方案之一。

Redus实现分布式锁,使用setNX (set if not exists)

getset(先写新值返回旧值,用于分辨是否是首次操做) 防止网络断开后 会设置超时

http://blog.csdn.net/ugg/article/details/41894947

SETNX 能够直接加锁操做,好比说对某个关键词foo加锁,客户端能够尝试

SETNX foo.lock

若是返回1,表示客户端已经获取锁,能够往下操做,操做完成后,经过

DEL foo.lock

命令来释放锁。

处理死锁

在上面的处理方式中,若是获取锁的客户端端执行时间过长,进程被kill掉,或者由于其余异常崩溃,致使没法释放锁,就会形成死锁。因此,须要对加锁要作时 效性检测。所以,咱们在加锁时,把当前时间戳做为value存入此锁中,经过当前时间戳和Redis中的时间戳进行对比,若是超过必定差值,认为锁已经时 效,防止锁无限期的锁下去,可是,在大并发状况,若是同时检测锁失效,并简单粗暴的删除死锁,再经过SETNX上锁,可能会致使竞争条件的产生,即多个客 户端同时获取锁。

C1获取锁,并崩溃。C2和C3调用SETNX上锁返回0后,得到foo.lock的时间戳,经过比对时间戳,发现锁超时。

C2 向foo.lock发送DEL命令。

C2 向foo.lock发送SETNX获取锁。

C3 向foo.lock发送DEL命令,此时C3发送DEL时,其实DEL掉的是C2的锁。

C3 向foo.lock发送SETNX获取锁。

此时C2和C3都获取了锁,产生竞争条件,若是在更高并发的状况,可能会有更多客户端获取锁。因此,DEL锁的操做,不能直接使用在锁超时的状况下,幸亏咱们有GETSET方法,假设咱们如今有另一个客户端C4,看看如何使用GETSET方式,避免这种状况产生。

C1获取锁,并崩溃。C2和C3调用SETNX上锁返回0后,调用GET命令得到foo.lock的时间戳T1,经过比对时间戳,发现锁超时。

C4 向foo.lock发送GESET命令,

GETSET foo.lock

并获得foo.lock中老的时间戳T2

若是T1=T2,说明C4得到时间戳。

若是T1!=T2,说明C4以前有另一个客户端C5经过调用GETSET方式获取了时间戳,C4未得到锁。只能sleep下,进入下次循环中。

如今惟一的问题是,C4设置foo.lock的新时间戳,是否会对锁产生影响。其实咱们能够看到C4和C5执行的时间差值极小,而且写入foo.lock中的都是有效时间错,因此对锁并无影响。

为了让这个锁更增强壮,获取锁的客户端,应该在调用关键业务时,再次调用GET方法获取T1,和写入的T0时间戳进行对比,以避免锁因其余状况被执行DEL 外解开而不知。以上步骤和状况,很容易从其余参考资料中看到。客户端处理和失败的状况很是复杂,不只仅是崩溃这么简单,还多是客户端由于某些操做被阻塞 了至关长时间,紧接着 DEL 命令被尝试执行(但这时锁却在另外的客户端手上)。也可能由于处理不当,致使死锁。还有可能由于sleep设置不合理,致使Redis在大并发下被压垮。 最为常见的问题还有

 AOF重写带有子进程副本保证安全

103. Java虚拟机Java内存结构,分区,每一个区放置什么

程序计数器:(线程私有)当前线程所执行的字节码的行号指示器,经过改变这个计数器的值来选取下一条须要执行的字节码的指令,以程序中分支、循环和跳转等流程的控制都离不开这个计数器的指示。

虚拟机栈:(线程私有),每一个方法在执行时都会建立一个栈桢,用于存储局部变量表、操做数栈、动态连接和方法出口等信息。一个方法从调用到执行完成的过程,对应的栈桢在虚拟机栈的进出过程。当线程结束时,虚拟机栈中的数据会被自动的释放。

局部变量表:基本数据类型、对象的引用、返回地址,局部变量表锁须要的内存空间是在程序编译时就已经会被肯定好的。

本地方法栈:(线程私有)虚拟机栈是为执行java方法所服务的,而本地方法栈是为了虚拟机使用到的本地方法锁服务的。

堆区:(线程共享)java堆是被全部的线程所共享的一片区域,全部的对象的实例和数组都会在堆区尽心分配。java堆细分:新生代和老年代;也可能会划分出多个线程锁共享额分配缓冲区TLAB;

Java堆能够在物理上不连续的内存空间中,只要逻辑上连续就能够。

方法区:(线程共享)存储已经被虚拟机加载过的类的信息、常量、静态变量和及时编译器编译后的代码。在方法区中一个区域叫作:运行时常量池,用于存放编译后生成的字面量和符号的引用。

堆的分代

(1)年轻代:

全部新生成的对象首先都是放在年轻代的。年轻代的目标就是尽量快速的收集掉那些生命周期短的对象。年轻代分三个区。一个Eden区,两个Survivor区(通常而言)。

大部分对象在Eden区中生成。当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当一个Survivor区满时,此区的存活对象将被复制到另一个Survivor区,当另外一个Survivor区也满了的时候,从前一个Survivor区复制过来的而且此时还存活的对象,将被复制“年老区(Tenured)”。

(2)年老代:

在年轻代中经历了N(可配置)次垃圾回收后仍然存活的对象,就会被放到年老代中。所以,能够认为年老代中存放的都是一些生命周期较长的对象。

(3)持久代:

用于存放静态数据,如 Java Class, Method 等。持久代对垃圾回收没有显著影响。

104. OOM异常的处理思路

对象的建立方法,对象的内存的分配,对象的访问定位

对象的建立:

(1)第一步,当遇到一个new的指令,首先去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并检查这个符号引用表明的类是否已经被加载、解析和初始化过。若是没有,须要先执行相应的类加载过程;

(2)第二步,根据类加载完成后肯定的内存大小,为对象分配内存;

(3)第三步,须要对分配到的内存空间都初始化为零值;

(4)第四步,虚拟机要对对象设置一些基本信息,如对象是那个类的实例、对象的哈希码、对象的GC分代年龄信息、如何才能找到类的元数据信息等,到这里虚拟机建立对象的工做已经完成;

(5)第五步,从程序的角度,咱们还须要对对象进行初始化操做。

对象的内存分配:

(1)对象头:

存储hashcode 、gc分代年龄以及一些必要的自身的运行时数据

(2)实例数据:

存储真实的数据信息

(3)对齐填充:

仅仅起到占位符的做用

对象的访问定位:

经过句柄池的访问,在句柄池中保存着到对象实例数据的指针以及到对象类型的数据的指针

经过直接的指针服访问,经过引用直接指向java堆的对象的实例数据

105. GC的三种收集方法:标记清除、标记整理、复制算法的原理与特色,分别用在什么地方,若是让你优化收集方法,有什么思路?

标记清除法:

就是先标记哪些对象实例不用,而后直接清除。缺点就是产生大量的内存碎片,下次若要存储一个大的对象,没法找到连续内存而又必须提早GC

标记整理:

也就是先标记,而后对存活的对象进行移动,所有移动到一端,而后再对其它的内存进行清理。

复制算法:

把内存分红相等的AB两块,每次只使用其中的一块。好比当A内存使用完后,就把A中还存活着的对象复制到另一块内存中去(B),而后再把已经使用过的内存清理掉。优势:这样就不用考虑内存碎片的问题了。缺点:内存减半,代价略高。

106. GC收集器有哪些?CMS收集器与G1收集器的特色。

对于新生代的收集器:

Serial单线程收集器 parnew多线程收集器  parallelSccavenge收集器

对于老年代的收集器:

CMS并发收集低停顿收集器  serial Old单线程收集器  parallel Old多线程收集器

107. CMS收集器:

优势:并发收集、低停顿

缺点:

(1)对cpu资源很是的敏感,在并发的阶段虽然不会致使用户的线程停顿,可是会因为占用一部分的线程致使应用程序变慢,总的吞吐量会下降;

(2)没法去处理浮动垃圾;

(3)基于“标记-清除”算法的收集器,因此会出现碎片。

114G1收集器:

优势:

(1)能充分利用cpu、多核的优点,使用多个cpu缩短停顿的时间;

(2)分代收集,不要其余收集器的配合即可以独立管理整个的GC堆;

(3)空间整合:总体基于“标记-清理”算法的实现,局部是基于“复制”算法的实现;

(4)能够预测的停顿

108. Minor GCFull GC分别在何时发生?

Minor GC:新生代GC,当jvm没法为一个新的对象分配空间时会触发

Full GC:整个堆空间的GC

109. 类加载的五个过程:加载、链接、初始化。

类的加载:将类的class文件读入内存,并建立一个叫作java.lang.Class对象,当程序中使用任何类时,系统都会为之创建一个java.lang.Class对象。

这些类的class文件的来源:

(1)从本地文件系统中加载class文件

(2)从jar包中加载class文件,好比jdbc编程时

(3)经过网络加载class文件

(4)把一个java源文件动态编译,并执行加载

链接:

(1)验证:验证阶段用于检验被加载的类是否具备正确的内部结构,并和其余的类协调一致

(2)准备:为类的类变量分配内存,并去设置默认的值

(3)解析:将类的二进制数据中的符号引用替换成直接引用。

初始化:

主要是对类变量进行初始化。

(1)若是该类尚未被加载和链接,则先进行加载链接

(2)若是该类的直接父类尚未被初始化,则先初始化其直接父类

(3)类中若是有初始化的语句则先去执行这些初始化语句。

110. 反射

概念:在运行的状态中,对于任何一个类或者对象,能够知道其任意的方法和属性,这种动态地调用其属性和方法的手段叫作反射。利用的反编译的手段

1、经过三种方式来获取Employee类型,获取类:

(1)Class c1 = Class.forName(“Employee”);

(2)Class c2 =Employee.class;

(3)Employee e = new Employee(); Class c3 = e.getClass();

2、获得class的实例:

Object o = c1.newInstance();

3、获取全部的属性

Field[] fs = c.getDeclaredFields();  

4、获取全部的方法

GetDeclareMethods();

动态代理

J2se多线程(线程锁)

线程的状态:

新建状态、就绪状态、运行状态、阻塞状态、死亡状态(线程状态转换图)

多线程的建立和启动:

(1)继承Thread类,重写类的run方法,调用对象的start方法启动

(2)实现Runnable接口,并重写该接口的run方法,该方法一样是线程的执行体,建立runnable实现类的实例,并以此实例做为Thread类的target来建立thread对象,该thread对象才是真的线程对象。

(3)使用Callable和Future接口建立线程。具体是建立Callable接口的实现类,并实现clall()方法。并使用FutureTask类来包装Callable实现类的对象,且以此FutureTask对象做为Thread对象的target来建立线程。

方法3:

// 建立MyCallable对象

Callable myCallable = new MyCallable();

//使用FutureTask来包装MyCallable对象

FutureTask ft = new FutureTask(myCallable);

//FutureTask对象做为Thread对象的target

Thread thread = new Thread(ft);

//线程进入到就绪状态

thread.start();   

线程同步的方法:sychronizedlockreentrantLock

synchronized修饰同步监视器:修饰可能被并发访问的共享资源充当同步监视器;

synchronized修饰方法,同步方法的同步监视器是this,也就是调用该方法的对象;

synchronizedd能够用来修饰方法,能够修饰代码块,可是不能修饰构造器和成员变量;

使用lock锁对象,每次只能有一个线程对lock对象进行加锁和释放锁,线程开始访问该锁对象时必须先得到锁lock

基本用法:

Private final ReentrantLock lock = new ReentrantLock();

Lock.lock();

Try(){

}catch(Exception e){

}finally{}

Lock.unlock();

锁的等级:内置锁、对象锁、类锁、方法锁。

内置锁:每个java对象均可以用作一个实现同步的锁,这个锁成为内置锁。当一个线程进入同步代码块或者方法的时候会自动得到该锁,在退出同步代码块或者方法时会释放该锁。

得到内置锁的方法:进入这个锁的保护的同步代码块或者方法

注意:java内置锁是一个互斥锁,最多只有一个线程可以得到该锁。

对象锁:对象锁是用于对象实例方法,或者一个对象实例上的。

类锁:类锁用于类的静态方法或者一个类的class对象上,一个类的对象实例有多个,可是每一个类只有一个class对象,即不一样对象实例的对象锁是互不干扰的,每个类都有一个类锁。类锁只是概念上的,并非真实存在的。

方法锁:synchronized修饰方法,同步方法的同步监视器是this,也就是调用该方法的对象;

111. ThreadLocal的设计理念与做用。

做用:

ThreadLocal类只能去建立一个被线程访问的变量,若是一段代码含有一个ThreadLocal变量的引用,即便两个线程同时执行这段代码,它们也没法访问到对方的ThreadLocal变量。

建立ThreadLocal的方式:

private ThreadLocal myThreadLocal = new ThreadLocal();

咱们能够看到,经过这段代码实例化了一个ThreadLocal对象。

咱们只须要实例化对象一次,而且也不须要知道它是被哪一个线程实例化。

虽然全部的线程都能访问到这个ThreadLocal实例,可是每一个线程却只能访问到本身经过调用ThreadLocal的set()方法设置的值。即便是两个不一样的线程在同一个ThreadLocal对象上设置了不一样的值,他们仍然没法访问到对方的值。

如何为ThreadLocal对象赋值和取值:

一旦建立了一个ThreadLocal变量,你能够经过以下代码设置某个须要保存的值:

myThreadLocal.set("A thread local value”);

能够经过下面方法读取保存在ThreadLocal变量中的值:

String threadLocalValue = (String) myThreadLocal.get();

get()方法返回一个Object对象,set()对象须要传入一个Object类型的参数。

初始化该ThreadLocal变量:

经过建立一个ThreadLocal的子类重写initialValue()方法,来为一个ThreadLocal对象指定一个初始值。

112. ThreadPool用法与优点。

优点:

第一:下降资源消耗。经过重复利用已建立的线程下降线程建立和销毁形成的消耗。

第二:提升响应速度。当任务到达时,任务能够不须要等到线程建立就能当即执行。

第三:提升线程的可管理性。线程是稀缺资源,若是无限制的建立,不只会消耗系统资源,还会下降系统的稳定性,使用线程池能够进行统一的分配,调优和监控。可是要作到合理的利用线程池,必须对其原理了如指掌。           

用法:

线程池的建立:

new  ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, milliseconds,runnableTaskQueue, handler);

参数:corePoolSize:线程池的基本大小

maximumPoolSize:线程池的最大大小

runnableTaskQueue:任务队列

keepAliveTime:线程活动保持时间

执行方式:

threadsPool.execute(handler);

threadsPool.submit(handler);

线程池的关闭:

Shutdown和shutdownNow方法实现

线程池的工做流程分析:

先将任务提交的顺序为核心线程池、队列、线程池、当这三个关节都不能执行用户所提交的线程时,则抛出“没法执行的任务”。     

113. 字节流和字符流

(1)java中字节流处理的最基本的单位是单个字节。一般用来处理二进制数据,最基本的两个字节流类是InputStream和OutputStream,这两个类都为抽象类。

字节流在默认的状况下是不支持缓存的。每次调用一次read方法都会请求操做系统来读取一个字节,每每会伴随一次磁盘的IO,若是要使用内存提升读取的效率,应该使用BufferedInputStream。

(2)字符流处理的最基本的单元是unicode(码元),一般用来来处理文本数据。

输入字符流(文件到内存):把要读取的字节序列按照指定的编码方式解码为相应的字符序列,从而能够存在内存中。

输出字符流(内存到文件):把要写入文件的字符序列转为指定的编码方式下的字节序列,而后写入文件中。

区别以下:

一、字节流操做的基本单元为字节;字符流操做的基本单元为Unicode码元。

unicode的编码范围:0x0000~0XFFFF,在这个范围的每一个数字都有一个字符与之对应

二、字节流默认不使用缓冲区;字符流使用缓冲区。

三、字节流一般用于处理二进制数据,实际上它能够处理任意类型的数据,但它不支持直接写入或读取Unicode码元;字符流一般处理文本数据,它支持写入及读取Unicode码元。

114. 序列化(常见的序列化操做)

含义:

java序列化:将java对象转换为字节序列的过程;

java反序列化:将字节序列恢复为java对象的过程

序列化的目的:

实现数据的持久化,将数据永久地保存在磁盘上,一般放在文件中;

利用序列化实现远程的通信,在网络上传送对象的字节序列.

实现序列化的三种方法:

1)某实体类仅仅实现了serializable接口(经常使用)

序列化步骤:

步骤一:建立一个对象输出流,它能够包装一个其它类型的目标输出流,如文件输出流:

ObjectOutputStream out = new ObjectOutputStream(new fileOutputStream(“D:\\objectfile.obj”));

步骤二:经过对象输出流的writeObject()方法写对象:

//Hello对象的字节流将输入到文件

out.writeObject(“Hello”);

反序列化步骤:

步骤一:建立一个对象输入流,它能够包装一个其它类型输入流,如文件输入流:

ObjectInputStream in = new ObjectInputStream(new fileInputStream(“D:\\objectfile.obj”));

步骤二:经过对象输出流的readObject()方法读取对象:

//将从文件中读取到字节序列转化为对象

String obj1 = (String)in.readObject();

2)若实体类仅仅实现了Serializable接口,而且还定义了readObject(ObjectInputStream in)writeObject(ObjectOutputSteam out),则采用如下方式进行序列化与反序列化。

ObjectOutputStream调用该对象的writeObject(ObjectOutputStream out)的方法进行序列化。

ObjectInputStream会调用该对象的readObject(ObjectInputStream in)的方法进行反序列化。

3)若Student类实现了Externalnalizable接口,且Student类必须实现readExternal(ObjectInput in)writeExternal(ObjectOutput out)方法,则按照如下方式进行序列化与反序列化。

ObjectOutputStream调用Student对象的writeExternal(ObjectOutput out))的方法进行序列化。

ObjectInputStream会调用Student对象的readExternal(ObjectInput in)的方法进行反序列化。

115. String,StringBuffer,StringBuilder的区别,应用场景

1)在执行的速度上:StringBuilder>StringBuffer>String

2)String是字符串常量 StringBuffer和StringBuilder是字符串变量

例子1:

String s = “abcd”;

s=s+1;

Syos(s);

底层执行:首先建立一个对象s,赋予abcd.而后又建立新的对象s,以前的对象并无发生变化,利用string操做字符串时,是在不断建立新的对象,而原来的对象因为没有了引用,会被GC,这样执行的效率会很低。

例子2:

String str2 = “This is only a”;

String str3 = “ simple”;

String str4 = “ test”;

String str1 = str2 +str3 + str4;

同理:str2 str3 str3没有被引用,可是建立了新的对象str1,执行速度上会很慢。

StringBuilder:线程非安全的

StringBuffer:线程安全的

例子3:

StringBuffer builder = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);

应用场景:

A:使用要操做少许的数据时,使用String

B:单线程操做字符串缓冲区下操做大量数据使用StringBulider

C:多线程操做字符串缓冲区下操做大量的数据使用StringBuffer

116. HashMapHashTable的区别

HashMap是线程不安全的;容许有null的键和值;执行的效率高一点;方法不是synchronize的要提供外同步;包含有containsvalue和containskey的方法

HashTable是线程安全的;不容许有null的键和值;效率稍微低些;方法是synchronize的;包含contains方法

117. GC垃圾回收机制原理

(参看博客)

118. ==与 equals区别

==:对于基本数据类型的变量,直接比较存储的值是否相等;做用于引用类型的变量,则比较的是该变量所指向的地址是否相同。

equals:不一样做用于基本数据类型的变量,若是没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址(至关于直接使用父类的equals方法,而该方法则是用==进行的比较,因此结果和用==比较的效果是同样的);可是好比String Date类对equals进行了重写,比较的是字面量。

119. final关键字

对于基本的数据类型,使用final关键字将使得数值恒定不变;

对于对象引用,final则是引用恒定不变,一但被初始化指向一个对象,它就不会再指向另一个对象,可是该对象自己是能够被修改的;

对于类,若是不想继承某个类,能够将该类设置为fianl形式,该类不会有子类;

对于方法,final修饰的方法不会被重写

对于空白的final,对于没有给定初始值的fianl,编译器会在使用前初始化该final修饰的变量

对于宏变量:被final修饰的变量为宏常量 在编译的阶段被其自己的值直接替换

short s1=1s1 s1+1

表达式类型的自动提高,一个short类型的变量和一个int型的数在一块儿进行运算,会将short类型的数隐式转换为int参与运算,可是该运算的结果为int类型是不一样直接赋值给一个short类型的,必须进行强制的类型转换,不然编译是通不过的。

120. 八种基本数据类型的大小,以及他们的封装类。

类型转换:byte (1字节)--->short(1)/char(2)--->int(4)--->long(8)--->float(4)--->double(8)

分装类:Byte Short Character Integer Long Float Double

121. Switch可否用string作参数?(分版本讨论)

(1)在jdk1.7版本前不支持string做为参数,仅仅支持byte、short、char,由于能够转换为int,可是long和string不能转换为int,因此不能使用。

(2)在jdk1.7以后,支持使用string做为case的参数,实际匹配的是该字符串的hash值,而后用equals进行安全性检查。Switch支持String实际上是一个语法糖,在编译后的字节码文件中都会被还原成原生的类型,并在相应的位置插入强制转换的代码,底层的JVM在switch上并无修改;当传入switch是null时,在运行时对一个null调用hashcode()方法,会抛出空指针异常。

122. Object有哪些公用方法?

object是全部类的父类,任何类都默认继承Object类

九、Clone

private保护方法,实现对象的浅复制,只有类实现了Cloneable接口才能够调用该方法,不然抛出CloneNotSupportException

十、Equals

在object中与==是同样的,子类通常须要重写该方法

十一、hashCode

该方法用于哈希查找,重写了equals方法通常都要重写hashcode方法,这个方法在一些具备哈希功能的collection中使用

十二、getClass

final方法,得到运行时的类型

1三、wait方法

使得当前的线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具备该对象的锁。Wait方法会一直等待,直到得到锁(到了睡眠的时间间隔也会唤醒本身)或者被中断掉。

调用该方法,当前的线程会进入到睡眠的状态,直到调用该对象的notify方法、notifyAll方法、调用interrupt中断该线程,时间间隔到了。

1四、Notify

唤醒在该对象上的等待的某个线程

1五、notifyAll

唤醒在该对象上的等待到全部的线程

1六、toString

把对象转换成string类型进行输出

123. Java的四种引用,强弱软虚,用到的场景。

引用的级别:

强引用>软引用>弱引用>虚引用

强引用:若是一个对象具备强引用,垃圾回收器绝对不会回收它。当内存空间不足时,jvm宁愿抛出outofmemoryError,使得程序的异常终止。

软引用:若是一个对象具备软引用,则内存空间足够,垃圾回收机制就不会去回收它,当内存不足时,就会进行回收。若是软引用所引用的对象被垃圾回收器回收,java虚拟机就会把这个软引用加入到与之关联的引用队列。

应用场景:实现内存敏感的高速缓存

弱引用:在垃圾回收器线程扫描它所管辖的内存区域的过程当中,一旦发现了只具备弱引用的对象,无论当前内存空间足够与否,都会回收它的内存。

应用场景:gc运行后终止

虚引用:就是形同虚设,与其余几种引用都不一样,虚引用并不会决定对象的生命周期。若是一个对象仅持有虚引用,那么它就和没有任何引用同样,在任什么时候候均可能被垃圾回收器回收。

124. 写出生产者消费者模式。

125. Hashcode的做用。

(1)Hashcode 的存在主要用于解决查找的快捷性,好比在hashmap、hashtable中,hashcode是用来在散列的存储结构中肯定对象的存储的位置的。

(2)若是两个对象相同,就是经过equals方法比较返回true,两个对象装在一个桶里,也就是hashcode也要必定相同。

(3)两个对象的hashcode相同,并不必定表明两个对象就是相同的,只能说明他们存储在一个桶里。

(4)通常重写了equals方法,也尽可能去重写hashcode方法,保证先找到该桶,再去找到对应的类,经过equals方法进行比较。

126. ArrayListLinkedListVector的区别。

1ArrayList:是基于动态数组的数据结构,LinkedList的基于链表的数据结构

二、对于随机访问get和set,ArrayList性能较好,由于LinkedList会去移动指针

三、对于新增和删除的操做,linkedList只须要修改指针的指向,性能较好,可是arrayList会移动数据。

vector的特色:

一、vector的方法都是线程同步的,是线程安全的,可是arraylist和linkedlist不是,因为线程的同步必然会影响性能,因此vector的性能不过高。

二、当vector或者arraylist的元素超过它的初始的大小时,vector会将容量翻倍,可是arraylist只会增长50%,这样有利于节约内存的空间。

127. MapSetListQueueStack的特色与用法。

128. HashMapConcurrentHashMap的区别

hashMap不是线程安全的;

concurrentHashMap是线程安全的;在其中引入了“分段锁”,而不是将全部的方法加上synchronized,由于那样就变成了hashtable.

所谓“分段锁”,就是把一个大的Map拆分红N个小的hashtable,根据key.hashcode()决定把key放在哪个hashtable中。

经过把整个Map分为N个Segment(相似HashTable),能够提供相同的线程安全,可是效率提高N倍,默认提高16倍。

129. TreeMapHashMapLindedHashMap的区别。

HashMap:根据键的hashcode值进行存储数据,根据键能够直接获取它的值,具备快速访问的特色,遍历时取得数据是随机的,hashmap最多只容许一条记录的键为null(set无序不重复),容许多条记录的值为Null;若是要保证线程的同步,应该使用Collections.synchronizedMap()方法进行包装,或者使用ConcurrentHashMap

LinkedHashMap:保存了记录的插入的顺序,在迭代遍历Linkedhashmap时,先获得的记录确定是先插入的,它遍历的速度只和实际的数据有关和容量没关。

TreeMap:实现的是SortMap,可以把保存的记录按照键进行排序,默认会按照键值的升序进行排序,当遍历TreeMap时获得的记录是排序事后的。

Collection包结构,与Collections的区别。

Collection是一个集合的接口,提供了对集合对象进行操做的通用的方法。

在它下面的子接口:set、list、map

java.util.Collections是一个包装的类,包含有各类的有关集合操做的静态方法,好比包含对集合的搜索、排序、线程安全化等一系列的操做,此类不能被实例化,至关因而操做集合的工具类,服务于java的collection的框架。

介绍下Concurrent

concurrent包基本有3个package组成

(1)java.util.concurrent:提供大部分关于并发的接口和类,如BlockingQueue,Callable,ConcurrentHashMap,ExecutorService, Semaphore等

 

(2)java.util.concurrent.atomic:提供全部原子操做的类,如AtomicInteger, AtomicLong等;

 

(3)java.util.concurrent.locks:提供锁相关的类, 如Lock, ReentrantLock, ReadWriteLock, Condition等;

concurrent包的优势:

1. 首先,功能很是丰富,诸如线程池(ThreadPoolExecutor),CountDownLatch等并发编程中须要的类已经有现成的实现,不须要本身去实现一套;毕竟jdk1.4对多线程编程的主要支持几乎就只有Thread, Runnable,synchronized等

2. concurrent包里面的一些操做是基于硬件级别的CAS(compare and swap),就是在cpu级别提供了原子操做,简单的说就能够提供无阻塞、无锁定的算法;而现代cpu大部分都是支持这样的算法的;

Try-catch -finallytry里有returnfinally还执行么?

任然会执行。

一、无论有木有出现异常,finally块中代码都会执行;

 

二、当try和catch中有return时,finally仍然会执行;

 

三、finally是在return后面的表达式运算后执行的(此时并无返回运算后的值,而是先把要返回的值保存起来,无论finally中的代码怎么样,返回的值都不会改变,任然是以前保存的值),因此函数返回值是在finally执行前肯定的;

 

四、finally中最好不要包含return,不然程序会提早退出,返回值不是try或catch中保存的返回值。

130. ExcptionError包结构。OOM你遇到过哪些状况,SOF你遇到过哪些状况。

131. Java面向对象的三个特征与含义。

封装:

是指将某事物的属性和行为包装到对象中,这个对象只对外公布须要公开的属性和行为,而这个公布也是能够有选择性的公布给其它对象。在Java中能使用private、protected、public三种修饰符或不用(即默认defalut)对外部对象访问该对象的属性和行为进行限制。

继承:

是子对象能够继承父对象的属性和行为,亦即父对象拥有的属性和行为,其子对象也就拥有了这些属性和行为。

多态:

java的引用变量有两种类型,一个是编译时的类型,一个是运行时的类型,编译时类型由申明该变量时的类型决定,运行时的类型由实际赋值给该变量的对象所决定,若是编译时的类型和运行时的类型不一致就可能出现所谓的多态。

在java中把一个子类的对象直接赋值给一个父类的引用变量,当运行该引用变量的方法时,其方法行为老是表现出子类方法的行为特征,这就有可能出现,相同类型的变量,调用同一个方法时呈现多种不一样的行为特征,出现了“多态”

132. OverrideOverload的含义和区别。

Overload:方法重载,在同一个类中,方法名相同,参数列表不一样,至于方法的修饰符,反回值的类型,与方法的重载没有任何的联系。

Override:方法重写,两同两小一大

两同:方法名称相同、参数列表相同

两小:返回值类型要小或者相等;抛出的异常要小或者相等

一大:子类方法的访问权限要相等或者更大

133. Interfaceabstract类的区别。

实例化:

都不能被实例化

类:一个类只能继承一次abstract类;一个类能够实现多个interface

数据成员:能够有本身的;接口的数据成员必须定义成static final的

方法:能够有私有的,非abstract方法必须实现;接口中不能够有私有的方法,默认都是public abstract的

变量:能够有私有的,其值能够在子类中从新定义,也能够从新赋值;接口中不能够有私有的成员变量,默认是public static final 实现类中不能去从新定义和改变其值

134. Java IONIO

IO是面向流的,NIO是面向缓冲区

Java NIO和IO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。 Java IO面向流意味着每次从流中读一个或多个字节,直至读取全部字节,它们没有被缓存在任何地方。此外,它不能先后移动流中的数据。若是须要先后移动从流中读取的数据,须要先将它缓存到一个缓冲区。 Java NIO的缓冲导向方法略有不一样。数据读取到一个它稍后处理的缓冲区,须要时可在缓冲区中先后移动。这就增长了处理过程当中的灵活性。可是,还须要检查是否该缓冲区中包含全部您须要处理的数据。并且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里还没有处理的数据。

阻塞与非阻塞IO

Java IO的各类流是阻塞的。这意味着,当一个线程调用read() write()时,该线程被阻塞,直到有一些数据被读取,或数据彻底写入。该线程在此期间不能再干任何事情了。 Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,可是它仅能获得目前可用的数据,若是目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,因此直至数据变的能够读取以前,该线程能够继续作其余的事情。非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不须要等待它彻底写入,这个线程同时能够去作别的事情。线程一般将非阻塞IO的空闲时间用于在其它通道上执行IO操做,因此一个单独的线程如今能够管理多个输入和输出通道(channel)。

选择器(Selectors)

Java NIO的选择器容许一个单独的线程来监视多个输入通道,你能够注册多个通道使用一个选择器,而后使用一个单独的线程来“选择”通道:这些通道里已经有能够处理的输入,或者选择已准备写入的通道。这种选择机制,使得一个单独的线程很容易来管理多个通道。

反射的做用原理。

见博客

135. wait()sleep()的区别。

(1)sleep方法,该方法属于thread类;wait方法属于object类

(2)sleep方法致使程序会暂停执行指定的时间,让出cpu给其余的线程,可是他仍是监控状态的保持者,当到达指定的时间又会自动恢复运行。也就是调用sleep方法线程不会释放对象锁;调用wait方法会释放对象锁,进入到等待此对象的等待锁定池,只有当针对此对象调用了notify()方法后,才会获取对象锁进入运行的状态。

136. foreach与正常for循环效率对比。

For循环能够从前向后遍历,也能够从后向前遍历,能够不逐个遍历,一般用于已知次数的循环。

foreach循环不能向迭代变量赋值,一般对集合对象从头到位进行读取,其有优化的存在。

137. JavaC++对比。

一、指针

java语言不提供指针,增长了自动的内存管理,有效的防止c/c++中的指针操做失误。

二、多重继承

C++支持多重继承,java不支持多重继承,可是容许实现多个接口。

三、数据类型和类

java将数据和方法结合起来,分装到类中,每一个对象均可以实现本身的特色和方法;而c++容许将函数和变量定义全局的。

四、内存管理

java能够对全部的对象进行内存管理,自动回收再也不使用的对象的内存;c++必须由程序员显式分配内存释放内存。

五、操做符的重载

C++支持操做符的重载,java不容许进行操做符的重载。

六、预处理功能

java不支持预处理功能,c++有一个预编译的阶段,也就是预处理器。

七、字符串

C++不支持字符串,java中支持字符串,是java的类对象。

八、数组

java引入了真正的数组,不一样于c++中利用指针实现的伪数组。

九、类型的转换

C++中有时会出现数据类型的隐含转换,设计到自动强制类型的转换问题,好比存在将浮点数直接转换为整数的状况,java不支持自动的强制类型转换,若是须要,必须显示进行强制的类型转换。

十、异常

java中使用try{}catch(){}finally{}进行异常的处理,c++没有。

138. HTTPHTTPS的区别

https:是http的安全版本,利用ssl能够对所传输的数据进行加密,默认端口是443

139. cookiesession的区别

(1)cookie数据存放在客户的浏览器上,session数据放在服务器上。 

(2)cookie不是很安全,别人能够分析存放在本地的COOKIE并进行COOKIE欺骗,若是主要考虑到安全应当使用session 

(3)session会在必定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,若是主要考虑到减轻服务器性能方面,应当使用COOKIE 

(4)单个cookie在客户端的限制是4K,就是说一个站点在客户端存放的COOKIE不能4K。

(5)因此:将登录信息等重要信息存放为SESSION;其余信息若是须要保留,能够放在COOKIE中

140. 网路TCP三次握手、四次挥手,各个状态的名称和含义timewait的做用?

ACK:tcp协议规定,只有ack=1时才有效,在链接创建后全部发送的豹纹的ack=1

Syn(SYNchronization):在链接创建时用来同步序号。

当SYN=1而ACK=0:这是一个链接请求报文;

当对方赞成创建链接时,则应该使得SYN=1并且ACK=1;

当SYN=1:这是一个链接请求或者链接接受报文

FIN(finis):终结的意思,用来释放一个链接。当fin=1,表示次报文段的发送方的数据已经发送完毕并要求释放链接。

A的状态:关闭状态--->同步已发送--->已创建

B的状态:关闭状态--->监听状态--->同步收到--->已创建

A:创建状态--->终止等待1--->终止等待2--->等待2MSL

B:创建状态--->关闭等待--->最后确认

Timewait的做用?

(1)为了保证A发送最后一个ACK报文能到达B,由于这个ACK报文有可能会丢失,这样会使得处在最后确认阶段的B收不到已经发送的FIN+ACK的确认信息,B会超时重传该报文段,在2MSL的时间内,A会收到信息,重传依次确认,重启该计时器。

(2)保证在2MSL的时间内,全部在本网络上产生的报文段都消失,使得在新的链接中不会出现旧的链接请求的报文段。

2)SYN攻击防范

141. TCP/IP层次架构,每层的做用和协议

OSI模型:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层

TCP/IP模型:应用层、传输层、网络互联层、主机到网络层

协议:

(1)应用层:FTP、TELNET、HTTP | SNMP、TFTP、NTP

将OSI模型的会话层和表示层整合成应用层,应用层面向不一样的网络应用引入了不一样的应用层协议。

(2)传输层:TCP|UDP

功能是使得源端主机和目标端主机上的对等实体能够进行会话,定义了两种服务质量不一样的协议,分别是TCP和UDP协议。

TCP协议是一个面向链接的、可靠的协议。它将一台主机发出的字节流无差错地发往互联网上的其余主机。在发送端,它负责把上层传送下来的字节流分红报文段并传递给下层。在接收端,它负责把收到的报文进行重组后递交给上层。TCP协议还要处理端到端的流量控制,以免缓慢接收的接收方没有足够的缓冲区接收发送方发送的大量数据。  

UDP协议是一个不可靠的、无链接协议。主要适用于不须要对报文进行排序和流量控制的场合。

(3)网络互联层:IP

网络互联层是整个TCP/IP协议栈的核心。功能是把分组发往目标网络或者主机。为了尽快发送分组,可能会沿着不一样的路径同时进行分组传递。所以,分组到达的顺序和发送的顺序可能会不一致,这就须要上层必须对分组进行排序。同时它能够将不一样类型的网络进行互联,完成拥塞控制的功能。

(4)主机到网络层:以太网、令牌环网、PPP

该层未被定义,具体的实现方式随着网络类型的不一样而不一样。

142. TCP拥塞控制

拥塞:计算机网络中的带宽、交换节点中的缓存和处理机都是网络中的资源,当在某一个时间,对网络中的某一个资源的需求超出了该资源所能提供的部分,网络的性能会变坏,就出现了拥塞。

拥塞控制:防止过多的数据注入到网路,使得网络中的路由器和链路不至于过载。拥塞控制是一个全局的过程,和流量控制不一样,流量控制是点对点的通讯量的控制。

慢开始和拥塞避免:

发送方维持一个叫作拥塞窗口的状态变量,拥塞窗口取决于网络的拥塞程度,而且会动态的变化。发送方让本身的发送窗口等于拥塞窗口,考虑接受方的接受能力,发送窗口可能会小于拥塞窗口。

慢开始算法:不要一开始就发送大量的数据,先探测下网络的拥塞程度,由小到大逐渐增长拥塞窗口的数量。

拥塞避免算法:让拥塞窗口缓慢增加,每进过一个往返时间就把发送方的拥塞窗口cwnd+1,而不是加倍,此时拥塞窗口按照线性的规律缓慢增加。

结合使用:为了防止拥塞窗口增加过大引起网络的拥塞,设置一个慢开始门限ssthresh状态变量。其用法:

当cwnd使用慢开始算法

当cwnd>ssthresh,使用拥塞避免算法

当cwnd=ssthresh,慢开始算法和拥塞避免算法随意。

当遇到网络拥塞时,就把慢开始门限设置为出现拥塞时发送窗口大小的一半,同时将拥塞的窗口设置为1,再从新开始执行慢开始算法。

143. 滑动窗口是什么设计的?

窗口:是一段能够被发送者发送的字节序列,其连续的范围称为“窗口”

滑动:这段“容许发送的范围”是随着发送的过程而不断变换的,表现的形式就是“按照顺序滑动”

流量控制:

(1)TCP利用滑动窗口实现流量的控制机制

(2)如何考虑流量控制中的传输效率

流量控制,接受方传递信息给发送方,使其发送数据不要太快,是一种端到端的控制,主要的方式是返回的ack中会包含本身的接受的窗口的大小,发送方收到该窗口的大小时会控制本身的数据发送。

传递效率:单个发送字节单个确认,和窗口有一个空余即通知发送方发送一个字节,会增长网络中许多没必要要的报文,由于会为一个字节数据添加40个字节的头部。

144. TCP/UDP的区别

一、TCP面向链接(如打电话要先拨号创建链接);UDP是无链接的,即发送数据以前不须要创建链接。

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

三、TCP面向字节流,其实是TCP把数据当作一连串无结构的字节流;UDP是面向报文的

UDP没有拥塞控制,所以网络出现拥塞不会使源主机的发送速率下降(对实时应用颇有用,如IP电话,实时视频会议等)

四、每一条TCP链接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通讯

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

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

145. TCP报文结构

紧急比特URG:URG=1,注解该报文应该尽快送达,而不须要按照原来的的队列次序依次送达

确认比特ACK:只有当ACK=1,确认序号字段才有意义

急迫比特PSH:当PSH=1时,注解恳求远地TCP将本报文段当即传送给应用层

复位比特RST:当注解呈现严重错误时,必须开释链接,进行从新的传输链接

同步比特SYN:当SYN=1而ACK=0时,这是一个链接请求报文段,若对方同意链接请求会将SYN=1并且ACK=1

终止比特FIN:当FIN=1,注解字符串已经发送完毕,并请求开释传输链接。

146. HTTP的报文结构(请求报文+响应报文)

HTTP请求报文:(1)请求行+(2)请求头部+(3)请求正文

(1)请求行:请求方法+URL+协议版本

请求方法:经常使用GET、POST

协议版本:HTTP/主版本号.次版本号  经常使用HTTP/1.0和HTTP/1.1

(2)为请求报文添加的一些附加的信息,“名/”组成,而且是每行一对 用冒号进行分割

在请求头部存在空行,表示请求头部的结束,接下来是请求正文!

区别get和post方式

对于get方式没有请求的正文,对于post方式有请求的正文。

HTTP响应的报文格式:

(1)状态行+(2)响应头部+(3)响应正文

(1)状态行:协议版本+状态码+状态码描述

(2)响应头部:也是由键值对所组成

(3)响应正文,由服务器端接受数据

147. HTTP状态码的含义

148. http request的几种类型(8种)

(1)OPTIONS:返回服务器针对特定资源所支持的HTTP请求方法。也能够利用向Web服务器发送'*'的请求来测试服务器的功能性。

(2)HEAD:向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法能够在没必要传输整个响应内容的状况下,就能够获取包含在响应消息头中的元信息。

(3)GET:向特定的资源发出请求。

(4)POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会致使新的资源的建立和/或已有资源的修改。

(5)PUT:向指定资源位置上传其最新内容。

(6)DELETE:请求服务器删除Request-URI所标识的资源。

(7)TRACE:回显服务器收到的请求,主要用于测试或诊断。

(8)CONNECT:HTTP/1.1协议中预留给可以将链接改成管道方式的代理服务器。

GET方式和POST方式对比:

GET方式:请求数据放在HTTP包头;使用明文传送,不安全;长度较小,通常为1024B;应用的场景为查询数据;若是传送的是英文数字或者是数字,直接发送,若是传送的是中文字符或则是其余的字符,则会进行BASE64编码

POST方式:请求数据放在HTTP正文;可明文或者密文传送,较为安全;长度通常没有限制;应用在修改数据上。

149. http1.0 http1.1的区别

(1)HTTP1.0 规定浏览与服务器只是保持短暂的链接,浏览器每次请求都须要和服务器创建一个TCP链接,服务器完成请求处理后当即断开TCP链接,服务器不去跟踪每一个客户也不去记录每一个客户过去的请求。HTTP1.0 不支持HOST请求字段

(2)HTTP1.1支持久链接,在一个TCP上能够传送多个HTTP请求和响应,减小了创建和关闭链接的消耗和延迟;

容许客户端不用等待上一次请求的返回结果,就能够去发送下一个请求,可是服务器端必须按照接受的客户端请求的前后顺序依次会送响应的结果,这样客户端才可以区分出每次请求的响应的内容。

HTTP1.0 支持HOST请求字段,这样就能够使用一个IP地址和端口号,在此基础上使用不一样的主机名建立多个虚拟的WEB站点;

HTTP1.1 提供了与身份认证、状态管理和cache缓存等机制

150. http怎么去处理长链接

http1.1 默认支持长链接,即一次tcp链接,容许发送多个http请求。

当web服务器看到keep-alive值时,会创建长链接。

151. 电脑上访问一个网页的整个过程是怎样的?DNSHTTPTCPOSPFIPARP

步骤1:当访问www.baidu.com时,会先从本地的host文件中获取该域名对应的IP地址,若是找不到就会用DNS协议来获取IP,在该DNS协议中,计算机会由本地的DNS服务器来解析该域名,最终找到对应的IP地址。

步骤2:接下来是使用TCP协议,创建TCP链接,在创建链接以前须要,为了将给服务器的消息带给服务器,则须要OSPF\IP\ARP协议的支持,IP告诉该消息从哪里出发,去向那里;消息的传送会通过一个个的路由器,OSPF会利用路由算法找出最佳的通往目的地址的路径;ARP负责找到下一个节点的地址,ARP协议使用的MAC地址,整个的发送的过程涉及到每个节点的MAP地址。

步骤3:经过步骤2的解析IP,如今能够和服务器创建TCP链接了,这时客户端即可以将Http请求数据发送给服务器端。服务器端进行处理,而后以http response的形式发送给客户端。

152. IP地址的分类

A类地址:1个字节的网络号+3个字节的主机地址  0.0.0.0~126.255.255.255

B类地址:2个字节的网络号+2个字节的主机地址  128.0.0.0~191.255.255.255

C类地址:3个字节的网络号+1个字节的主机地址  192.0.0.0~223.255.255.255

D类地址:多播地址

E类地址:保留为从此使用

153. 路由器和交换机的区别

交换机:为数据桢从一个端口到另一个端口的转发提供了低时延、低开销的通路,使得任意端口接受的数据帧都可以从其余的端口送出。

路由器:网络链接和路由选择,用于网络层的数据转发。

154. 如何设计一个高并发的系统?

① 数据库的优化,包括合理的事务隔离级别、SQL语句优化、索引的优化

使用缓存,尽可能减小数据库 IO

③ 分布式数据库、分布式缓存

④ 服务器的负载均衡

155. 设计模式简单工厂模式

有一个抽象的产品父类将全部的具体的产品抽象出来,达到复用的目的。同时有一个简单工厂维护一个对抽象产品的依赖,在该简单工厂中去负责实例的建立,在该工厂中去实例不一样的对象,每每须要利用case判断语句去动态实例化相关的类。

工厂方法模式

建立对象的接口,让子类去决定具体实例化的对象,把简单的内部逻辑的判断,转移到了客户端,让客户端去动态地实例化相关的子类。工厂方法模式克服了简单工厂违背开放-封闭原则的特色。

抽象工厂模式

提供建立一系列相关或者相互依赖对象的接口,而无需指定他们具体的类。

职责链模式

使得多个对象都有机会去处理请求,从而避免请求的发送者和接受者之间的耦合关系,将这些对象连成一条链,并沿着这条链去传递该请求,直到有一个对象处理它为之。

单例模式

2)恶汉式的单例模式

利用静态static的方式进行实例化,在类被加载时就会建立实例。

/**

 * 饿汉式实现单例模式

 */

public class Singleton {

  private static Singleton instance = new Singleton();

    private Singleton() {

    }

    public static Singleton getInstance() {

        return instance;

    }

}

(6)懒汉式实现单例模式

在被第一次引用时才去建立对象。

/**

 * 懒汉式实现单例模式

 */

public class Singleton {

    private static Singleton instance;//建立私有的静态变量

    private Singleton() {//私有的构造函数

    }

    // synchronized方法,多线程状况下保证单例对象惟一

public static synchronized Singleton getInstance() {

//若是实例对象为空,就从新去实例化

        if (instance == null) {

            instance = new Singleton();

        }

        return instance;

    }

}

分析:这中方法的实现,效率不高,由于该方法定义为同步的方法。

(7)双重锁实现的单例模式

/**

 * DCL实现单例模式

 */

public class Singleton {

    private static Singleton instance = null;

    private Singleton() {

    }

    public static Singleton getInstance() {

        // 两层判空,第一层是为了不没必要要的同步

        // 第二层是为了在null的状况下建立实例

        if (instance == null) {

            synchronized (Singleton.class) {

                if (instance == null) {

                    instance = new Singleton();

                }

            }

        }

        return instance;

    }

}

分析:资源的利用率较高,在须要的时候去初始化实例,并且能够保证线程的安全,该方法没有去进行同步锁,效率比较好。

(8)静态内部类实现单例模式

/**

 * 静态内部类实现单例模式

 */

public class Singleton {

    private Singleton() {

}

//返回实例的方法

    public static Singleton getInstance() {

        return SingletonHolder.instance;

    }

    /**

     * 静态内部类

     */

private static class SingletonHolder {

    //静态私有的实例对象

        private static Singleton instance = new Singleton();

    }

}

分析:第一次加载类时不会去初始化instance,只有第一次调用getInstance()方法时,虚拟机才会加载内部类,初始化instance

能够保证线程的安全,单例对象的惟一,延迟了单例的初始化。

(9)枚举单例

/**

 * 枚举实现单例模式

 */

public enum SingletonEnum {

    INSTANCE;

    public void doSomething() {

        System.out.println("do something");

    }

}

分析:枚举实例的建立是线程安全的,即便反序列化也不会生成新的实例,在任何的状况下都是单例的。

适配器模式

将一个类的接口转换成客户但愿的另一个接口,使得本来因为接口步兼容而不能一块儿工做的类变得能够一块儿工做。

target是咱们所指望的接口的类型,包含一个request方法,经过使用adapter去实现该接口,并实现其中的request方法,在adapter中创建一个私有的adaptee对象,在adapter重写的方法中去调用specificRequest方法,这样适配器adapter就构建好了。只须要在客户端,建立adapter实例,调用request方法就能够利用多态的方式,实现了specificRequest()方法。

观察者模式

定义了一种一对多的依赖关系,让多个观察者能够同时去监听某一个主题对象,这个主题对象在状态发生变化时,会通知全部的观察者对象,使得他们可以自动更新本身。

Subject:把全部对观察者对象的引用保存在一个汇集里,每一个主题均可以有任何数量的观察者,能够增长删除观察者对象。

Observer:抽象观察者,为全部的具体的观察者定义一个接口,在获得主题时更新本身。

concreteObserver:具体的观察者,实现更新的方法

concreteSubject:具体的主题

做用:应用在一个对象改变时,须要改变其余的对象,并且具体不知道有多少个对象须要改变,将耦合的双方都依赖于抽象而不是依赖于具体,从而使得各自的变化都不会影响到另一边的变化。

大整数BigInteger  大浮点数 BigDecimal

java运算的优先级:优先级相同时比较结合性:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

java 高并发

156. 一、线程与进程

进程是一个实体。每个进程都有它本身的地址空间,通常状况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。

一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程本身不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的所有资源。

区别不一样 
a,地址空间:进程内的一个执行单元;进程至少有一个线程;它们共享进程的地址空间;而进程有本身独立的地址空间; 
b,资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资 
c,线程是处理器调度的基本单位,但进程不是. 
d,两者都可并发执行.

157. 二、 守护线程

Java中有两类线程:用户线程 (User Thread)、守护线程 (Daemon Thread)。 
守护线程和用户线程的区别在于:守护线程依赖于建立它的线程,而用户线程则不依赖。举个简单的例子:若是在main线程中建立了一个守护线程,当main方法运行完毕以后,守护线程也会随着消亡。而用户线程则不会,用户线程会一直运行直到其运行完毕。在JVM中,像垃圾收集器线程就是守护线程。

158. 三、java thread状态

NEW 状态是指线程刚建立, 还没有启动

RUNNABLE 状态是线程正在正常运行中, 固然可能会有某种耗时计算/IO等待的操做/CPU时间片切换等, 这个状态下发生的等待通常是其余系统资源, 而不是锁, Sleep等

BLOCKED 这个状态下, 是在多个线程有同步操做的场景, 好比正在等待另外一个线程的synchronized 块的执行释放, 也就是这里是线程在等待进入临界区

WAITING 这个状态下是指线程拥有了某个锁以后, 调用了他的wait方法, 等待其余线程/锁拥有者调用 notify / notifyAll 一遍该线程能够继续下一步操做, 这里要区分 BLOCKED 和 WATING 的区别, 一个是在临界点外面等待进入, 一个是在理解点里面wait等待别人notify, 线程调用了join方法 join了另外的线程的时候, 也会进入WAITING状态, 等待被他join的线程执行结束

TIMED_WAITING 这个状态就是有限的(时间限制)的WAITING, 通常出如今调用wait(long), join(long)等状况下, 另一个线程sleep后, 也会进入TIMED_WAITING状态

TERMINATED 这个状态下表示 该线程的run方法已经执行完毕了, 基本上就等于死亡了(当时若是线程被持久持有, 可能不会被回收)

159. 四、请说出与线程同步以及线程调度相关的方法。

wait():使一个线程处于等待(阻塞)状态,而且释放所持有的对象的锁;

sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要处理InterruptedException异常;

notify():唤醒一个处于等待状态的线程,固然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM肯定唤醒哪一个线程,并且与优先级无关;

notityAll():唤醒全部处于等待状态的线程,该方法并非将对象的锁给全部线程,而是让它们竞争,只有得到锁的线程才能进入就绪状态;

160. 五、进程调度算法

实时系统FIFO(First Input First Output,先进先出算法),SJF(Shortest Job First,最短做业优先算法),SRTF(Shortest Remaining Time First,最短剩余时间优先算法)。 
交互式系统RR(Round Robin,时间片轮转算法),HPF(Highest Priority First,最高优先级算法),多级队列,最短进程优先,保证调度,彩票调度,公平分享调度。

161. 六、wait()和sleep()的区别

sleep来自Thread类,和wait来自Object类

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

sleep睡眠后不出让系统资源,wait让出系统资源其余线程能够占用CPU

sleep(milliseconds)须要指定一个睡眠时间,时间一到会自动唤醒

162. 七、ThreadLocal,以及死锁分析

hreadLocal为每一个线程维护一个本地变量。 
采用空间换时间,它用于线程间的数据隔离,为每个使用该变量的线程提供一个副本,每一个线程均可以独立地改变本身的副本,而不会和其余线程的副本冲突。 
ThreadLocal类中维护一个Map,用于存储每个线程的变量副本,Map中元素的键为线程对象,而值为对应线程的变量副本。 
完全理解ThreadLocal

163. 八、Synchronized 与Lock

ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候 
线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O的锁定, 
若是使用 synchronized ,若是A不释放,B将一直等下去,不能被中断 
若是 使用ReentrantLock,若是A不释放,能够使B在等待了足够长的时间之后,中断等待,而干别的事情

ReentrantLock获取锁定与三种方式: 
a) lock(), 若是获取了锁当即返回,若是别的线程持有锁,当前线程则一直处于休眠状态,直到获取锁 
b) tryLock(), 若是获取了锁当即返回true,若是别的线程正持有锁,当即返回false; 
c)tryLock(long timeout,TimeUnit unit), 若是获取了锁定当即返回true,若是别的线程正持有锁,会等待参数给定的时间,在等待的过程当中,若是获取了锁定,就返回true,若是等待超时,返回false; 
d) lockInterruptibly:若是获取了锁定当即返回,若是没有获取锁定,当前线程处于休眠状态,直到或者锁定,或者当前线程被别的线程中断

整体的结论先摆出来:

synchronized: 
在资源竞争不是很激烈的状况下,偶尔会有同步的情形下,synchronized是很合适的。缘由在于,编译程序一般会尽量的进行优化synchronized,另外可读性很是好,无论用没用过5.0多线程包的程序员都能理解。 
ReentrantLock: 
ReentrantLock提供了多样化的同步,好比有时间限制的同步,能够被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在资源竞争不激烈的情形下,性能稍微比synchronized差点点。可是当同步很是激烈的时候,synchronized的性能一会儿能降低好几十倍。而ReentrantLock确还能维持常态。

164. 九、Volatile和Synchronized

Volatile和Synchronized四个不一样点:

粒度不一样,前者针对变量 ,后者锁对象和类

syn阻塞,volatile线程不阻塞

syn保证三大特性,volatile不保证原子性

syn编译器优化,volatile不优化 
要使 volatile 变量提供理想的线程安全,必须同时知足下面两个条件: 

对变量的写操做不依赖于当前值。

该变量没有包含在具备其余变量的不变式中。

165. 十、CAS

CAS是乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知此次竞争中失败,并能够再次尝试。CAS有3个操做数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改成B,不然什么都不作。

166. 十一、Java中Unsafe类详解

经过Unsafe类能够分配内存,能够释放内存;类中提供的3个本地方法allocateMemory、reallocateMemory、freeMemory分别用于分配内存,扩充内存和释放内存,与C语言中的3个方法对应。

能够定位对象某字段的内存位置,也能够修改对象的字段值,即便它是私有的;

挂起与恢复:将一个线程进行挂起是经过park方法实现的,调用 park后,线程将一直阻塞直到超时或者中断等条件出现。unpark能够终止一个挂起的线程,使其恢复正常。整个并发框架中对线程的挂起操做被封装在 LockSupport类中,LockSupport类中有各类版本pack方法,但最终都调用了Unsafe.park()方法。

cas 
Java中Unsafe类详解

167. 十二、线程池

线程池的做用: 
在程序启动的时候就建立若干线程来响应处理,它们被称为线程池,里面的线程叫工做线程 
第一:下降资源消耗。经过重复利用已建立的线程下降线程建立和销毁形成的消耗。 
第二:提升响应速度。当任务到达时,任务能够不须要等到线程建立就能当即执行。 
第三:提升线程的可管理性。 
经常使用线程池:ExecutorService 是主要的实现类,其中经常使用的有 
Executors.newSingleT 
hreadPool(),newFixedThreadPool(),newcachedTheadPool(),newScheduledThreadPool()。

168. 1三、ThreadPoolExecutor

构造方法参数说明

corePoolSize:核心线程数,默认状况下核心线程会一直存活,即便处于闲置状态也不会受存keepAliveTime限制。除非将allowCoreThreadTimeOut设置为true。 
maximumPoolSize:线程池所能容纳的最大线程数。超过这个数的线程将被阻塞。当任务队列为没有设置大小的LinkedBlockingDeque时,这个值无效。 
keepAliveTime:非核心线程的闲置超时时间,超过这个时间就会被回收。 
unit:指定keepAliveTime的单位,如TimeUnit.SECONDS。当将allowCoreThreadTimeOut设置为true时对corePoolSize生效。 
workQueue:线程池中的任务队列. 
经常使用的有三种队列,SynchronousQueue,LinkedBlockingDeque,ArrayBlockingQueue。

threadFactory:线程工厂,提供建立新线程的功能。ThreadFactory是一个接口,只有一个方法

原理

若是当前池大小 poolSize 小于 corePoolSize ,则建立新线程执行任务。

若是当前池大小 poolSize 大于 corePoolSize ,且等待队列未满,则进入等待队列

若是当前池大小 poolSize 大于 corePoolSize 且小于 maximumPoolSize ,且等待队列已满,则建立新线程执行任务。

若是当前池大小 poolSize 大于 corePoolSize 且大于 maximumPoolSize ,且等待队列已满,则调用拒绝策略来处理该任务。

线程池里的每一个线程执行完任务后不会马上退出,而是会去检查下等待队列里是否还有线程任务须要执行,若是在 keepAliveTime 里等不到新的任务了,那么线程就会退出。

1三、Executor拒绝策略

AbortPolicy:为java线程池默认的阻塞策略,不执行此任务,并且直接抛出一个运行时异常,切记ThreadPoolExecutor.execute须要try 
catch,不然程序会直接退出.

DiscardPolicy:直接抛弃,任务不执行,空方法

DiscardOldestPolicy:从队列里面抛弃head的一个任务,并再次execute 此task。

CallerRunsPolicy:在调用execute的线程里面执行此command,会阻塞入

用户自定义拒绝策略:实现RejectedExecutionHandler,并本身定义策略模式

169. 1四、CachedThreadPool 、 FixedThreadPool、SingleThreadPool

newSingleThreadExecutor :建立一个单线程化的线程池,它只会用惟一的工做线程来执行任务, 保证全部任务按照指定顺序(FIFO, LIFO, 优先级)执行 
适用场景:任务少 ,而且不须要并发执行

newCachedThreadPool :建立一个可缓存线程池,若是线程池长度超过处理须要,可灵活回收空闲线程,若无可回收,则新建线程. 
线程没有任务要执行时,便处于空闲状态,处于空闲状态的线程并不会被当即销毁(会被缓存住),只有当空闲时间超出一段时间(默认为60s)后,线程池才会销毁该线程(至关于清除过期的缓存)。新任务到达后,线程池首先会让被缓存住的线程(空闲状态)去执行任务,若是没有可用线程(无空闲线程),便会建立新的线程。 
适用场景:处理任务速度 > 提交任务速度,耗时少的任务(避免无限新增线程)

newFixedThreadPool :建立一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

newScheduledThreadPool:建立一个定长线程池,支持定时及周期性任务执行

170. 1五、CopyOnWriteArrayList

CopyOnWriteArrayList : 写时加锁,当添加一个元素的时候,将原来的容器进行copy,复制出一个新的容器,而后在新的容器里面写,写完以后再将原容器的引用指向新的容器,而读的时候是读旧容器的数据,因此能够进行并发的读,但这是一种弱一致性的策略。 
使用场景:CopyOnWriteArrayList适合使用在读操做远远大于写操做的场景里,好比缓存。

1六、AQS

AQS使用一个int成员变量来表示同步状态,经过内置的FIFO队列来完成获取资源线程的排队工做。

private volatile int state;//共享变量,使用volatile修饰保证线程可见性

1

2种同步方式:独占式,共享式。独占式如ReentrantLock,共享式如Semaphore,CountDownLatch,组合式的如ReentrantReadWriteLock

节点的状态 
CANCELLED,值为1,表示当前的线程被取消; 
SIGNAL,值为-1,表示当前节点的后继节点包含的线程须要运行,也就是unpark; 
CONDITION,值为-2,表示当前节点在等待condition,也就是在condition队列中; 
PROPAGATE,值为-3,表示当前场景下后续的acquireShared可以得以执行; 
值为0,表示当前节点在sync队列中,等待着获取锁。

模板方法模式 
 protected boolean tryAcquire(int arg) : 独占式获取同步状态,试着获取,成功返回true,反之为false 
 protected boolean tryRelease(int arg) :独占式释放同步状态,等待中的其余线程此时将有机会获取到同步状态; 
 protected int tryAcquireShared(int arg) :共享式获取同步状态,返回值大于等于0,表明获取成功;反之获取失败; 
 protected boolean tryReleaseShared(int arg) :共享式释放同步状态,成功为true,失败为false 
AQS维护一个共享资源state,经过内置的FIFO来完成获取资源线程的排队工做。该队列由一个一个的Node结点组成,每一个Node结点维护一个prev引用和next引用,分别指向本身的前驱和后继结点。双端双向链表。 

独占式:乐观的并发策略 
acquire 
 a.首先tryAcquire获取同步状态,成功则直接返回;不然,进入下一环节; 
b.线程获取同步状态失败,就构造一个结点,加入同步队列中,这个过程要保证线程安全; 
 c.加入队列中的结点线程进入自旋状态,如果老二结点(即前驱结点为头结点),才有机会尝试去获取同步状态;不然,当其前驱结点的状态为SIGNAL,线程即可安心休息,进入阻塞状态,直到被中断或者被前驱结点唤醒。 
release 
release的同步状态相对简单,须要找到头结点的后继结点进行唤醒,若后继结点为空或处于CANCEL状态,从后向前遍历找寻一个正常的结点,唤醒其对应线程。

共享式
共享式地获取同步状态.同步状态的方法tryAcquireShared返回值为int。 
a.当返回值大于0时,表示获取同步状态成功,同时还有剩余同步状态可供其余线程获取; 
 b.当返回值等于0时,表示获取同步状态成功,但没有可用同步状态了; 
 c.当返回值小于0时,表示获取同步状态失败。

AQS实现公平锁和非公平锁 
非公平锁中,那些尝试获取锁且还没有进入等待队列的线程会和等待队列head结点的线程发生竞争。公平锁中,在获取锁时,增长了isFirst(current)判断,当且仅当,等待队列为空或当前线程是等待队列的头结点时,才可尝试获取锁。 
 Java并发包基石-AQS详解

171. 1六、Java里的阻塞队列

7个阻塞队列。分别是

ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列。 
LinkedBlockingQueue :一个由链表结构组成的有界阻塞队列。 
PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列。 
DelayQueue:一个使用优先级队列实现的无界阻塞队列。 
SynchronousQueue:一个不存储元素的阻塞队列。 
LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。 
LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。

添加元素

Java中的阻塞队列接口BlockingQueue继承自Queue接口。BlockingQueue接口提供了3个添加元素方法。 
add:添加元素到队列里,添加成功返回true,因为容量满了添加失败会抛出IllegalStateException异常 
offer:添加元素到队列里,添加成功返回true,添加失败返回false 
put:添加元素到队列里,若是容量满了会阻塞直到容量不满

删除方法

3个删除方法 
poll:删除队列头部元素,若是队列为空,返回null。不然返回元素。 
remove:基于对象找到对应的元素,并删除。删除成功返回true,不然返回false 
take:删除队列头部元素,若是队列为空,一直阻塞到队列有元素并删除

172. 1七、condition

Condition的源码理解,主要就是理解等待队列,等待队列能够类比同步队列,并且等待队列比同步队列要简单,由于等待队列是单向队列,同步队列是双向队列。

java condition使用及分

173. 1八、DelayQueue

队列中每一个元素都有个过时时间,而且队列是个优先级队列,当从队列获取元素时候,只有过时元素才会出队列。

并发队列-无界阻塞延迟队列delayqueue原理探究

174. 1九、Fork/Join框架

 Fork/Join框架是Java 7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每一个小任务结果后获得大任务结果的框架。Fork/Join框架要完成两件事情:

  1.任务分割:首先Fork/Join框架须要把大的任务分割成足够小的子任务,若是子任务比较大的话还要对子任务进行继续分割

  2.执行任务并合并结果:分割的子任务分别放到双端队列里,而后几个启动线程分别从双端队列里获取任务执行。子任务执行完的结果都放在另一个队列里,启动一个线程从队列里取数据,而后合并这些数据。

  在Java的Fork/Join框架中,使用两个类完成上述操做

  1.ForkJoinTask:咱们要使用Fork/Join框架,首先须要建立一个ForkJoin任务。该类提供了在任务中执行fork和join的机制。一般状况下咱们不须要直接集成ForkJoinTask类,只须要继承它的子类,Fork/Join框架提供了两个子类:

    a.RecursiveAction:用于没有返回结果的任务

    b.RecursiveTask:用于有返回结果的任务

  2.ForkJoinPool:ForkJoinTask须要经过ForkJoinPool来执行

  任务分割出的子任务会添加到当前工做线程所维护的双端队列中,进入队列的头部。当一个工做线程的队列里暂时没有任务时,它会随机从其余工做线程的队列的尾部获取一个任务(工做窃取算法)。 
Fork/Join框架的实现原理 
  ForkJoinPool由ForkJoinTask数组和ForkJoinWorkerThread数组组成,ForkJoinTask数组负责将存放程序提交给ForkJoinPool,而ForkJoinWorkerThread负责执行这

20、原子操做类

java.util.concurrent.atomic包下,能够分为四种类型的原子更新类:原子更新基本类型、原子更新数组类型、原子更新引用和原子更新属性。

原子更新基本类型 
使用原子方式更新基本类型,共包括3个类: 
AtomicBoolean:原子更新布尔变量 
AtomicInteger:原子更新整型变量 
AtomicLong:原子更新长整型变量

原子更新数组 
经过原子更新数组里的某个元素,共有3个类: 
AtomicIntegerArray:原子更新整型数组的某个元素 
AtomicLongArray:原子更新长整型数组的某个元素 
AtomicReferenceArray:原子更新引用类型数组的某个元素 
AtomicIntegerArray经常使用的方法有: 
int addAndSet(int i, int delta):以原子方式将输入值与数组中索引为i的元素相加 
boolean compareAndSet(int i, int expect, int update):若是当前值等于预期值,则以原子方式更新数组中索引为i的值为update值

原子更新引用类型 
AtomicReference:原子更新引用类型 
AtomicReferenceFieldUpdater:原子更新引用类型里的字段 
AtomicMarkableReference:原子更新带有标记位的引用类型。

原子更新字段类 
若是须要原子更新某个类的某个字段,就须要用到原子更新字段类,能够使用如下几个类: 
AtomicIntegerFieldUpdater:原子更新整型字段 
AtomicLongFieldUpdater:原子更新长整型字段 
AtomicStampedReference:原子更新带有版本号的引用类型。 
要想原子更新字段,须要两个步骤: 
每次必须使用newUpdater建立一个更新器,而且须要设置想要更新的类的字段 
更新类的字段(属性)必须为public volatile

2一、同步屏障CyclicBarrier

CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要作的事情是,让一组线程到达一个屏障(也能够叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,全部被屏障拦截的线程才会继续干活。CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每一个线程调用await方法告诉CyclicBarrier我已经到达了屏障,而后当前线程被阻塞。 
CyclicBarrier和CountDownLatch的区别

CountDownLatch的计数器只能使用一次。而CyclicBarrier的计数器能够使用reset() 方法重置。因此CyclicBarrier能处理更为复杂的业务场景,好比若是计算发生错误,能够重置计数器,并让线程们从新执行一次。 
CyclicBarrier还提供其余有用的方法,好比getNumberWaiting方法能够得到CyclicBarrier阻塞的线程数量。isBroken方法用来知道阻塞的线程是否被中断。好比如下代码执行完以后会返回true。

175. 2二、Semaphore

Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它经过协调各个线程,以保证合理的使用公共资源 
Semaphore能够用于作流量控制,特别公用资源有限的应用场景,好比数据库链接。假若有一个需求,要读取几万个文件的数据,由于都是IO密集型任务,咱们能够启动几十个线程并发的读取,可是若是读到内存后,还须要存储到数据库中,而数据库的链接数只有10个,这时咱们必须控制只有十个线程同时获取数据库链接保存数据,不然会报错没法获取数据库链接。这个时候,咱们就能够使用Semaphore来作流控,代码以下:

控制并发线程数的Semaphore

176. 2三、死锁,以及解决死锁

死锁产生的四个必要条件

互斥条件:资源是独占的且排他使用,进程互斥使用资源,即任意时刻一个资源只能给一个进程使用,其余进程若申请一个资源,而该资源被另外一进程占有时,则申请者等待直到资源被占有者释放。 
不可剥夺条件:进程所得到的资源在未使用完毕以前,不被其余进程强行剥夺,而只能由得到该资源的进程资源释放。 
请求和保持条件:进程每次申请它所须要的一部分资源,在申请新的资源的同时,继续占用已分配到的资源。 
循环等待条件:在发生死锁时必然存在一个进程等待队列{P1,P2,…,Pn},其中P1等待P2占有的资源,P2等待P3占有的资源,…,Pn等待P1占有的资源,造成一个进程等待环路,环路中每个进程所占有的资源同时被另外一个申请,也就是前一个进程占有后一个进程所深情地资源。

解决死锁

一是死锁预防,就是不让上面的四个条件同时成立。 
二是,合理分配资源。 
三是使用银行家算法,若是该进程请求的资源操做系统剩余量能够知足,那么就分配。

177. 2四、进程间的通讯方式

管道( pipe):管道是一种半双工的通讯方式,数据只能单向流动,并且只能在具备亲缘关系的进程间使用。进程的亲缘关系一般是指父子进程关系。

有名管道 (named pipe) : 有名管道也是半双工的通讯方式,可是它容许无亲缘关系进程间的通讯。

信号量( semophore ) : 信号量是一个计数器,能够用来控制多个进程对共享资源的访问。它常做为一种锁机制,防止某进程正在访问共享资源时,其余进程也访问该资源。所以,主要做为进程间以及同一进程内不一样线程之间的同步手段。

消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。

信号 ( sinal ) : 信号是一种比较复杂的通讯方式,用于通知接收进程某个事件已经发生。

共享内存( shared memory ) :共享内存就是映射一段能被其余进程所访问的内存,这段共享内存由一个进程建立,但多个进程均可以访问。共享内存是最快的 IPC 方式,它是针对其余进程间通讯方式运行效率低而专门设计的。它每每与其余通讯机制,如信号量,配合使用,来实现进程间的同步和通讯。

套接字( socket ) : 套解口也是一种进程间通讯机制,与其余通讯机制不一样的是,它可用于不一样机器间的进程通讯。

中断

interrupt()的做用是中断本线程。 
本线程中断本身是被容许的;其它线程调用本线程的interrupt()方法时,会经过checkAccess()检查权限。这有可能抛出SecurityException异常。 
若是本线程是处于阻塞状态:调用线程的wait(), wait(long)或wait(long, int)会让它进入等待(阻塞)状态,或者调用线程的join(), join(long), join(long, int), sleep(long), sleep(long, int)也会让它进入阻塞状态。若线程在阻塞状态时,调用了它的interrupt()方法,那么它的“中断状态”会被清除而且会收到一个InterruptedException异常。例如,线程经过wait()进入阻塞状态,此时经过interrupt()中断该线程;调用interrupt()会当即将线程的中断标记设为“true”,可是因为线程处于阻塞状态,因此该“中断标记”会当即被清除为“false”,同时,会产生一个InterruptedException的异常。 
若是线程被阻塞在一个Selector选择器中,那么经过interrupt()中断它时;线程的中断标记会被设置为true,而且它会当即从选择操做中返回。 
若是不属于前面所说的状况,那么经过interrupt()中断线程时,它的中断标记会被设置为“true”。 
中断一个“已终止的线程”不会产生任何操做。

终止处于“阻塞状态”的线程 
一般,咱们经过“中断”方式终止处于“阻塞状态”的线程。 
当线程因为被调用了sleep(), wait(), join()等方法而进入阻塞状态;若此时调用线程的interrupt()将线程的中断标记设为true。因为处于阻塞状态,中断标记会被清除,同时产生一个InterruptedException异常。将InterruptedException放在适当的为止就能终止线程, 

终止处于“运行状态”的线程

interrupted() 和 isInterrupted()的区别

最后谈谈 interrupted() 和 isInterrupted()。 
interrupted() 和 isInterrupted()都可以用于检测对象的“中断标记”。 
区别是,interrupted()除了返回中断标记以外,它还会清除中断标记(即将中断标记设为false);而isInterrupted()仅仅返回中断标记。 
interrupt()和线程终止方式

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

178. 一、经常使用设计模式

单例模式:懒汉式、饿汉式、双重校验锁、静态加载,内部类加载、枚举类加载。保证一个类仅有一个实例,并提供一个访问它的全局访问点。

代理模式:动态代理和静态代理,何时使用动态代理。

适配器模式:将一个类的接口转换成客户但愿的另一个接口。适配器模式使得本来因为接口不兼容而不能一块儿工做的那些类能够一块儿工做。

装饰者模式:动态给类加功能。

观察者模式:有时被称做发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知全部观察者对象,使它们可以自动更新本身。

策略模式:定义一系列的算法,把它们一个个封装起来, 而且使它们可相互替换。

外观模式:为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

命令模式:将一个请求封装成一个对象,从而使您能够用不一样的请求对客户进行参数化。

建立者模式:将一个复杂的构建与其表示相分离,使得一样的构建过程能够建立不一样的表示。

抽象工厂模式:提供一个建立一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

 

179. 二、基础知识

Java基本类型哪些,所占字节和范围

Set、List、Map的区别和联系

何时使用Hashmap

何时使用Linkedhashmap、Concurrenthashmap、Weakhashmap

哪些集合类是线程安全的

为何Set、List、map不实现Cloneable和Serializable接口

Concurrenthashmap的实现,1.7和1.8的实现

Arrays.sort的实现

何时使用CopyOnArrayList

volatile的使用

synchronied的使用

reentrantlock的实现和Synchronied的区别

CAS的实现原理以及问题

AQS的实现原理

接口和抽象类的区别,何时使用

类加载机制的步骤,每一步作了什么,static和final修改的成员变量的加载时机

双亲委派模型

反射机制:反射动态擦除泛型、反射动态调用方法等

动态绑定:父类引用指向子类对象

JVM内存管理机制:有哪些区域,每一个区域作了什么

JVM垃圾回收机制:垃圾回收算法 垃圾回收器 垃圾回收策略

jvm参数的设置和jvm调优

什么状况产生年轻代内存溢出、什么状况产生年老代内存溢出

内部类:静态内部类和匿名内部类的使用和区别

Redismemcached:何时选择redis,何时选择memcached,内存模型和存储策略是什么样的

MySQL的基本操做 主从数据库一致性维护

mysql的优化策略有哪些

mysql索引的实现 B+树的实现原理

什么状况索引不会命中,会形成全表扫描

java中bio nio aio的区别和联系

为何bio是阻塞的 nio是非阻塞的 nio是模型是什么样的

Java io的总体架构和使用的设计模式

Reactor模型和Proactor模型

http请求报文结构和内容

http三次握手和四次挥手

rpc相关:如何设计一个rpc框架,从io模型 传输协议 序列化方式综合考虑

Linux命令 统计,排序,前几问题等

StringBuff 和StringBuilder的实现,底层实现是经过byte数据,外加数组的拷贝来实现的

cas操做的使用

内存缓存和数据库的一致性同步实现

微服务的优缺点

线程池的参数问题

ip问题 如何判断ip是否在多个ip段中

判断数组两个中任意两个数之和是否为给定的值

乐观锁和悲观锁的实现

synchronized实现原理

你在项目中遇到的困难和怎么解决的

你在项目中完成的比较出色的亮点

消息队列广播模式和发布/订阅模式的区别

生产者消费者代码实现

死锁代码实现

线程池:参数,每一个参数的做用,几种不一样线程池的比较,阻塞队列的使用,拒绝策略

Future和ListenableFuture 异步回调相关

算法相关:判断可否从数组中找出两个数字和为给定值,随机生成1~10000不重复并放入数组,求数组的子数组的最大和,二分查找算法的实现及其时间复杂计算

 

180. 三、其它

算法:经常使用排序算法,二分查找,链表相关,数组相关,字符串相关,树相关等

常见序列化协议及其优缺点

memcached内存原理,为何是基于块的存储

搭建一个rpc须要准备什么

若是线上服务器频繁地出现full gc ,如何去排查

若是某一时刻线上机器忽然量变得很大,服务扛不住了,怎么解决

LUR算法的实现

LinkedHashMap实现LRU

定义栈的数据结构,请在该类型中实现一个可以找到栈最小元素的min函数

海量数据处理的解决思路

reactor模型的演变

阻塞、非阻塞、同步、异步区别

Collection的子接口

jvm调优相关

zookeeper相关,节点类型,如何实现服务发现和服务注册

nginx负载均衡相关,让你去实现负载均衡,该怎么实现

linux命令,awk、cat、sort、cut、grep、uniq、wc、top等

压力测试相关,怎么分析,单接口压测和多状况下的压测

你以为你的有点是什么,你的缺点是什么

spring mvc的实现原理

netty底层实现,IO模型,ChannelPipeline的实现和原理

缓存的设计和优化

缓存和数据库一致性同步解决方案

你所在项目的系统架构,谈谈总体实现

消息队列的使用场景

ActiveMQ、RabbitMQ、Kafka的区别

 

 

 

 

 

 

 

 

 

 

181. 1、Java基础

一、String类为何是final的。

二、HashMap的源码,实现原理,底层结构。

三、说说你知道的几个Java集合类:list、set、queue、map实现类咯。。。

四、描述一下ArrayList和LinkedList各自实现和区别

五、Java中的队列都有哪些,有什么区别。

六、反射中,Class.forName和classloader的区别

七、Java七、Java8的新特性(baidu问的,好BT)

八、Java数组和链表两种结构的操做效率,在哪些状况下(从开头开始,从结尾开始,从中间开始),哪些操做(插入,查找,删除)的效率高

九、Java内存泄露的问题调查定位:jmap,jstack的使用等等

十、string、stringbuilder、stringbuffer区别

十一、hashtable和hashmap的区别

1三、异常的结构,运行时异常和非运行时异常,各举个例子

1四、String a= “abc” String b = "abc" String c = new String("abc") String d = "ab" + "c" .他们之间用 == 比较的结果

1五、String 类的经常使用方法

1六、Java 的引用类型有哪几种

1七、抽象类和接口的区别

1八、java的基础类型和字节大小。

1九、Hashtable,HashMap,ConcurrentHashMap 底层实现原理与线程安全问题(建议熟悉 jdk 源码,才能从容应答)

20、若是不让你用Java Jdk提供的工具,你本身实现一个Map,你怎么作。说了很久,说了HashMap源代码,若是我作,就会借鉴HashMap的原理,说了一通HashMap实现

2一、 Hash冲突怎么办?哪些解决散列冲突的方法?

2二、HashMap冲突很厉害,最差性能,你会怎么解决?从O(n)提高到log(n)咯,用二叉排序树的思路说了一通

2三、rehash

2四、hashCode() 与 equals() 生成算法、方法怎么重写

182. 2、Java IO

一、讲讲IO里面的常见类,字节流、字符流、接口、实现类、方法阻塞。

二、讲讲NIO。

三、String 编码UTF-8 和GBK的区别?

四、何时使用字节流、何时使用字符流?

五、递归读取文件夹下的文件,代码怎么实现

183. 3、Java Web

一、session和cookie的区别和联系,session的生命周期,多个服务部署时session管理。

二、servlet的一些相关问题

三、webservice相关问题

四、jdbc链接,forname方式的步骤,怎么声明使用一个事务。举例并具体代码

五、无框架下配置web.xml的主要配置内容

六、jsp和servlet的区别 

184. 4、JVM

一、Java的内存模型以及GC算法

二、jvm性能调优都作了什么

三、介绍JVM中7个区域,而后把每一个区域可能形成内存的溢出的状况说明

四、介绍GC 和GC Root不正常引用。

五、本身从classload 加载方式,加载机制说开去,从程序运行时数据区,讲到内存分配,讲到String常量池,讲到JVM垃圾回收机制,算法,hotspot。反正就是各类扩展

六、jvm 如何分配直接内存, new 对象如何不分配在堆而是栈上,常量池解析

七、数组多大放在 JVM 老年代(不仅是设置 PretenureSizeThreshold ,问一般多大,没作过一问便知)

八、老年代中数组的访问方式

九、GC 算法,永久代对象如何 GC , GC 有环怎么处理

十、谁会被 GC ,何时 GC

十一、若是想不被 GC 怎么办

十二、若是想在 GC 中生存 1 次怎么办

185. 5、开源框架

一、hibernate和ibatis的区别

二、讲讲mybatis的链接池。

三、spring框架中须要引用哪些jar包,以及这些jar包的用途

4. springMVC的原理

五、springMVC注解的意思

六、spring中beanFactory和ApplicationContext的联系和区别

七、spring注入的几种方式(循环注入)

八、spring如何实现事物管理的

九、springIOC

十、spring AOP的原理

十一、hibernate中的1级和2级缓存的使用方式以及区别原理(Lazy-Load的理解)

十二、Hibernate的原理体系架构,五大核心接口,Hibernate对象的三种状态转换,事务管理。

186. 6、多线程

一、Java建立线程以后,直接调用start()方法和run()的区别

二、经常使用的线程池模式以及不一样线程池的使用场景

三、newFixedThreadPool此种线程池若是线程数达到最大值后会怎么办,底层原理。

四、多线程之间通讯的同步问题,synchronized锁的是对象,衍伸出和synchronized相关不少的具体问题,例如同一个类不一样方法都有synchronized锁,一个对象是否能够同时访问。或者一个类的static构造方法加上synchronized以后的锁的影响。

五、了解可重入锁的含义,以及ReentrantLock 和synchronized的区别

六、同步的数据结构,例如concurrentHashMap的源码理解以及内部实现原理,为何他是同步的且效率高

七、atomicinteger和volatile等线程安全操做的关键字的理解和使用

八、线程间通讯,wait和notify

九、定时线程的使用

十、场景:在一个主线程中,要求有大量(不少不少)子线程执行完以后,主线程才执行完成。多种方式,考虑效率。

十一、进程和线程的区别

十二、什么叫线程安全?举例说明

1三、线程的几种状态

1四、并发、同步的接口或方法

1五、HashMap 是否线程安全,为什么不安全。 ConcurrentHashMap,线程安全,为什么安全。底层实现是怎么样的。

1六、J.U.C下的常见类的使用。 ThreadPool的深刻考察; BlockingQueue的使用。(take,poll的区别,put,offer的区别);原子类的实现。

1七、简单介绍下多线程的状况,从创建一个线程开始。而后怎么控制同步过程,多线程经常使用的方法和结构

1八、volatile的理解

1九、实现多线程有几种方式,多线程同步怎么作,说说几个线程里经常使用的方法

187. 7、网络通讯

一、http是无状态通讯,http的请求方式有哪些,能够本身定义新的请求方式么。

二、socket通讯,以及长链接,分包,链接异常断开的处理。

三、socket通讯模型的使用,AIO和NIO。

四、socket框架netty的使用,以及NIO的实现原理,为何是异步非阻塞。

五、同步和异步,阻塞和非阻塞。

六、OSI七层模型,包括TCP,IP的一些基本知识

七、http中,get post的区别

八、说说http,tcp,udp之间关系和区别。

九、说说浏览器访问www.taobao.com,经历了怎样的过程。

十、HTTP协议、  HTTPS协议,SSL协议及完整交互过程;

十一、tcp的拥塞,快回传,ip的报文丢弃

十二、https处理的一个过程,对称加密和非对称加密

1三、head各个特色和区别

1四、说说浏览器访问www.taobao.com,经历了怎样的过程。

188. 8、数据库MySql

一、MySql的存储引擎的不一样

二、单个索引、联合索引、主键索引

三、Mysql怎么分表,以及分表后若是想按条件分页查询怎么办(若是不是按分表字段来查询的话,几乎效率低下,无解)

四、分表以后想让一个id多个表是自增的,效率实现

五、MySql的主从实时备份同步的配置,以及原理(从库读主库的binlog),读写分离

六、写SQL语句。。。

七、索引的数据结构,B+树

八、事务的四个特性,以及各自的特色(原子、隔离)等等,项目怎么解决这些问题

九、数据库的锁:行锁,表锁;乐观锁,悲观锁

十、数据库事务的几种粒度;

十一、关系型和非关系型数据库区别

189. 9、设计模式 

一、单例模式:饱汉、饿汉。以及饿汉中的延迟加载,双重检查

二、工厂模式、装饰者模式、观察者模式。

三、工厂方法模式的优势(低耦合、高内聚,开放封闭原则) 

190. 10、算法 

一、使用随机算法产生一个数,要求把1-1000W之间这些数所有生成。(考察高效率,解决产生冲突的问题)

二、两个有序数组的合并排序

三、一个数组的倒序

四、计算一个正整数的正平方根

五、说白了就是常见的那些查找、排序算法以及各自的时间复杂度

六、二叉树的遍历算法

七、DFS,BFS算法

九、比较重要的数据结构,如链表,队列,栈的基本理解及大体实现。

十、排序算法与时空复杂度(快排为何不稳定,为何你的项目还在用)

十一、逆波兰计算器

十二、Hoffman 编码

1三、查找树与红黑树 

191. 11、并发与性能调优 

一、有个每秒钟5k个请求,查询手机号所属地的笔试题(记得不完整,没列出),如何设计算法?请求再多,好比5w,如何设计整个系统?

二、高并发状况下,咱们系统是如何支撑大量的请求的

三、集群如何同步会话状态

四、负载均衡的原理

五、若是有一个特别大的访问量,到数据库上,怎么作优化(DB设计,DBIO,SQL优化,Java优化)

六、若是出现大面积并发,在不增长服务器的基础上,如何解决服务器响应不及时问题“。

七、假如你的项目出现性能瓶颈了,你以为可能会是哪些方面,怎么解决问题。

八、如何查找 形成 性能瓶颈出现的位置,是哪一个位置照成性能瓶颈。

九、你的项目中使用过缓存机制吗?有没用用户非本地缓存 

192. 12、其余 

一、 经常使用的linux下的命令

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

SPRING

193. 一、什么是Spring框架?Spring框架有哪些主要模块?

Spring框架是一个为Java应用程序的开发提供了综合、普遍的基础性支持的Java平台。

Spring帮助开发者解决了开发中基础性的问题,使得开发人员能够专一于应用程序的开发。

Spring框架自己亦是按照设计模式精心打造,这使得咱们能够在开发环境中安心的集成Spring框架,没必要担忧Spring是如何在后台进行工做的。

Spring框架至今已集成了20多个模块。这些模块主要被分以下图所示的核心容器、数据访问/集成,、Web、AOP(面向切面编程)、工具、消息和测试模块。

 

194. 二、使用Spring框架能带来哪些好处?

下面列举了一些使用Spring框架带来的主要好处:

  • Dependency Injection(DI) 方法使得构造器和JavaBean properties文件中的依赖关系一目了然。
  • EJB容器相比较,IoC容器更加趋向于轻量级。这样一来IoC容器在有限的内存和CPU资源的状况下进行应用程序的开发和发布就变得十分有利。
  • Spring并无闭门造车,Spring利用了已有的技术好比ORM框架、logging框架、J2EE、Quartz和JDK Timer,以及其余视图技术。
  • Spring框架是按照模块的形式来组织的。由包和类的编号就能够看出其所属的模块,开发者仅仅须要选用他们须要的模块便可。
  • 测试一项用Spring开发的应用程序十分简单,由于测试相关的环境代码都已经囊括在框架中了。更加简单的是,利用JavaBean形式的POJO类,能够很方便的利用依赖注入来写入测试数据。
  • Spring的Web框架亦是一个精心设计的Web MVC框架,为开发者们在web框架的选择上提供了一个除了主流框架好比Struts、过分设计的、不流行web框架的之外的有力选项。
  • Spring提供了一个便捷的事务管理接口,适用于小型的本地事物处理(好比在单DB的环境下)和复杂的共同事物处理(好比利用JTA的复杂DB环境)。

195. 三、什么是控制反转(IOC)?什么是依赖注入?

控制反转是应用于软件工程领域中的,在运行时被装配器对象来绑定耦合对象的一种编程技巧,对象之间耦合关系在编译时一般是未知的。在传统的编程方式中,业务逻辑的流程是由应用程序中的早已被设定好关联关系的对象来决定的。在使用控制反转的状况下,业务逻辑的流程是由对象关系图来决定的,该对象关系图由装配器负责实例化,这种实现方式还能够将对象之间的关联关系的定义抽象化。而绑定的过程是经过“依赖注入”实现的。

控制反转是一种以给予应用程序中目标组件更多控制为目的设计范式,并在咱们的实际工做中起到了有效的做用。

依赖注入是在编译阶段还没有知所需的功能是来自哪一个的类的状况下,将其余对象所依赖的功能对象实例化的模式。这就须要一种机制用来激活相应的组件以提供特定的功能,因此依赖注入是控制反转的基础。不然若是在组件不受框架控制的状况下,框架又怎么知道要建立哪一个组件?

Java中依然注入有如下三种实现方式:

  1. 构造器注入
  2. Setter方法注入
  3. 接口注入

196. 四、请解释下Spring框架中的IoC?

Spring中的 org.springframework.beans 包和 org.springframework.context包构成了Spring框架IoC容器的基础。

BeanFactory 接口提供了一个先进的配置机制,使得任何类型的对象的配置成为可能。ApplicationContex接口对BeanFactory(是一个子接口)进行了扩展,在BeanFactory的基础上添加了其余功能,好比与Spring的AOP更容易集成,也提供了处理message resource的机制(用于国际化)、事件传播以及应用层的特别配置,好比针对Web应用的WebApplicationContext。

org.springframework.beans.factory.BeanFactory 是Spring IoC容器的具体实现,用来包装和管理前面提到的各类bean。BeanFactory接口是Spring IoC 容器的核心接口。

IOC:把对象的建立、初始化、销毁交给spring来管理,而不是由开发者控制,实现控制反转。

 

197. 五、BeanFactory和ApplicationContext有什么区别?

BeanFactory 能够理解为含有bean集合的工厂类。BeanFactory 包含了种bean的定义,以便在接收到客户端请求时将对应的bean实例化。

BeanFactory还能在实例化对象的时生成协做类之间的关系。此举将bean自身与bean客户端的配置中解放出来。BeanFactory还包含了bean生命周期的控制,调用客户端的初始化方法(initialization methods)和销毁方法(destruction methods)。

从表面上看,application context如同bean factory同样具备bean定义、bean关联关系的设置,根据请求分发bean的功能。但applicationcontext在此基础上还提供了其余的功能。

  1. 提供了支持国际化的文本消息
  2. 统一的资源文件读取方式
  3. 已在监听器中注册的bean的事件

如下是三种较常见的 ApplicationContext 实现方式:

一、ClassPathXmlApplicationContext:从classpath的XML配置文件中读取上下文,并生成上下文定义。应用程序上下文从程序环境变量中取得。

[html] view plain copy

  1. ApplicationContext context = new ClassPathXmlApplicationContext(“bean.xml”);    

二、FileSystemXmlApplicationContext :由文件系统中的XML配置文件读取上下文。

[html] view plain copy

  1. ApplicationContext context = new FileSystemXmlApplicationContext(“bean.xml”);   

三、XmlWebApplicationContext:由Web应用的XML文件读取上下文。

 

198. 六、Spring有几种配置方式?

Spring配置到应用开发中有如下三种方式:

  1. 基于XML的配置
  2. 基于注解的配置
  3. 基于Java的配置

199. 七、如何用基于XML配置的方式配置Spring?

Spring框架中,依赖和服务须要在专门的配置文件来实现,我经常使用的XML格式的配置文件。这些配置文件的格式一般用<beans>开头,而后一系列的bean定义和专门的应用配置选项组成。

SpringXML配置的主要目的时候是使全部的Spring组件均可以用xml文件的形式来进行配置。这意味着不会出现其余的Spring配置类型(好比声明的方式或基于Java Class的配置方式)

Spring的XML配置方式是使用被Spring命名空间的所支持的一系列的XML标签来实现的。Spring有如下主要的命名空间:context、beans、jdbc、tx、aop、mvc和aso。

如:

[html] view plain copy

  1. <beans>    
  2. <!-- JSON Support -->    
  3. <bean name="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"/>    
  4. <bean name="jsonTemplate" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>    
  5. <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"/>    
  6. </beans>   

下面这个web.xml仅仅配置了DispatcherServlet,这件最简单的配置便能知足应用程序配置运行时组件的需求。

 

200. 八、如何用基于Java配置的方式配置Spring?

Spring对Java配置的支持是由@Configuration注解和@Bean注解来实现的。由@Bean注解的方法将会实例化、配置和初始化一个新对象,这个对象将由Spring的IoC容器来管理。@Bean声明所起到的做用与<bean/> 元素相似。被@Configuration所注解的类则表示这个类的主要目的是做为bean定义的资源。被@Configuration声明的类能够经过在同一个类的内部调用@bean方法来设置嵌入bean的依赖关系。

最简单的@Configuration 声明类请参考下面的代码:

[java] view plain copy

  1. @Configuration    
  2. public class AppConfig{    
  3. @Bean    
  4. public MyService myService() {    
  5. return new MyServiceImpl();    
  6. }    
  7. }   

对于上面的@Beans配置文件相同的XML配置文件以下:

[html] view plain copy

  1. <beans>    
  2. <bean id="myService" class="com.somnus.services.MyServiceImpl"/>    
  3. </beans>   

上述配置方式的实例化方式以下:利用AnnotationConfigApplicationContext 类进行实例化

 

要使用组件组建扫描,仅需用@Configuration进行注解便可:

[java] view plain copy

  1. @Configuration    
  2. @ComponentScan(basePackages = "com.somnus")    
  3. public class AppConfig  {    
  4. ...    
  5. }   

在上面的例子中,com.acme包首先会被扫到,而后再容器内查找被@Component 声明的类,找到后将这些类按照Sring bean定义进行注册。

若是你要在你的web应用开发中选用上述的配置的方式的话,须要用AnnotationConfigWebApplicationContext 类来读取配置文件,能够用来配置Spring的Servlet监听器ContextLoaderListener或者Spring MVC的DispatcherServlet。

201. 九、怎样用注解的方式配置Spring?

Spring在2.5版本之后开始支持用注解的方式来配置依赖注入。能够用注解的方式来替代XML方式的bean描述,能够将bean描述转移到组件类的内部,只须要在相关类上、方法上或者字段声明上使用注解便可。注解注入将会被容器在XML注入以前被处理,因此后者会覆盖掉前者对于同一个属性的处理结果。

注解装配在Spring中是默认关闭的。因此须要在Spring文件中配置一下才能使用基于注解的装配模式。若是你想要在你的应用程序中使用关于注解的方法的话,请参考以下的配置。

[html] view plain copy

  1. <beans>    
  2. <context:annotation-config/>    
  3. <!-- bean definitions go here -->    
  4. </beans>    

 <context:annotation-config/>标签配置完成之后,就能够用注解的方式在Spring中向属性、方法和构造方法中自动装配变量。

下面是几种比较重要的注解类型:

  1. @Required:该注解应用于设值方法。
  2. @Autowired:该注解应用于有值设值方法、非设值方法、构造方法和变量。
  3. @Qualifier:该注解和@Autowired注解搭配使用,用于消除特定bean自动装配的歧义。
  4. JSR-250 Annotations:Spring支持基于JSR-250 注解的如下注解,@Resource、@PostConstruct 和 @PreDestroy。

202. 十、请解释Spring Bean的生命周期?

Spring Bean的生命周期简单易懂。在一个bean实例被初始化时,须要执行一系列的初始化操做以达到可用的状态。一样的,当一个bean不在被调用时须要进行相关的析构操做,并从bean容器中移除。

Spring bean factory 负责管理在spring容器中被建立的bean的生命周期。Bean的生命周期由两组回调(call back)方法组成。

  1. 初始化以后调用的回调方法。
  2. 销毁以前调用的回调方法。

Spring框架提供了如下四种方式来管理bean的生命周期事件:

  • InitializingBean和DisposableBean回调接口
  • 针对特殊行为的其余Aware接口
  • Bean配置文件中的Custom init()方法和destroy()方法
  • @PostConstruct和@PreDestroy注解方式

使用customInit() customDestroy()方法管理bean生命周期的代码样例以下:

[html] view plain copy

  1. <beans>    
  2. <bean id="demoBean" class="com.somnus.task.DemoBean" init-method="customInit" destroy-method="customDestroy"></bean>    
  3. </beans>    

203. 十一、Spring Bean的做用域之间有什么区别?

Spring容器中的bean能够分为5个范围。全部范围的名称都是自说明的,可是为了不混淆,仍是让咱们来解释一下:

  1. singleton:这种bean范围是默认的,这种范围确保无论接受到多少个请求,每一个容器中只有一个bean的实例,单例的模式由bean factory自身来维护。
  2. prototype:原形范围与单例范围相反,为每个bean请求提供一个实例。
  3. request:在请求bean范围内会每个来自客户端的网络请求建立一个实例,在请求完成之后,bean会失效并被垃圾回收器回收。
  4. Session:与请求范围相似,确保每一个session中有一个bean的实例,在session过时后,bean会随之失效。
  5. global-session:global-session和Portlet应用相关。当你的应用部署在Portlet容器中工做时,它包含不少portlet。若是你想要声明让全部的portlet共用全局的存储变量的话,那么这全局变量须要存储在global-session中。

全局做用域与Servlet中的session做用域效果相同。

204. 十二、什么是Spring inner beans?

Spring框架中,不管什么时候bean被使用时,当仅被调用了一个属性。一个明智的作法是将这个bean声明为内部bean。内部bean能够用setter注入“属性”和构造方法注入“构造参数”的方式来实现。

好比,在咱们的应用程序中,一个Customer类引用了一个Person类,咱们的要作的是建立一个Person的实例,而后在Customer内部使用。

内部bean的声明方式以下:

 

205. 1三、Spring框架中的单例Beans是线程安全的么?

Spring框架并无对单例bean进行任何多线程的封装处理。关于单例bean的线程安全和并发问题须要开发者自行去搞定。但实际上,大部分的Spring bean并无可变的状态(好比Serview类和DAO类),因此在某种程度上说Spring的单例bean是线程安全的。若是你的bean有多种状态的话(好比 View Model 对象),就须要自行保证线程安全。
最浅显的解决办法就是将多态bean的做用域由“singleton”变动为“prototype”。

206. 1四、请举例说明如何在Spring中注入一个Java Collection?

Spring提供了如下四种集合类的配置元素:

  • <list> :   该标签用来装配可重复的list值。
  • <set> :    该标签用来装配没有重复的set值。
  • <map>:   该标签可用来注入键和值能够为任何类型的键值对。
  • <props> : 该标签支持注入键和值都是字符串类型的键值对。

下面看一下具体的例子:

 

207. 1五、如何向Spring Bean中注入一个Java.util.Properties?

第一种方法是使用以下面代码所示的<props> 标签:

也可用”util:”命名空间来从properties文件中建立出一个propertiesbean,而后利用setter方法注入bean的引用。

208. 1六、请解释Spring Bean的自动装配?

Spring框架中,在配置文件中设定bean的依赖关系是一个很好的机制,Spring容器还能够自动装配合做关系bean之间的关联关系。这意味着Spring能够经过向Bean Factory中注入的方式自动搞定bean之间的依赖关系。自动装配能够设置在每一个bean上,也能够设定在特定的bean上。

下面的XML配置文件代表了如何根据名称将一个bean设置为自动装配:

[html] view plain copy

  1. <bean id="employeeDAO" class="com.howtodoinjava.EmployeeDAOImpl" autowire="byName" />   

除了bean配置文件中提供的自动装配模式,还能够使用@Autowired注解来自动装配指定的bean。在使用@Autowired注解以前须要在按照以下的配置方式在Spring配置文件进行配置才能够使用。

[html] view plain copy

  1. <context:annotation-config />  

也能够经过在配置文件中配置AutowiredAnnotationBeanPostProcessor 达到相同的效果。

[html] view plain copy

  1. <bean class ="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>    

配置好之后就能够使用@Autowired来标注了。

 

209. 1七、请解释自动装配模式的区别?

Spring框架中共有5种自动装配,让咱们逐一分析。

  1. no:这是Spring框架的默认设置,在该设置下自动装配是关闭的,开发者须要自行在bean定义中用标签明确的设置依赖关系。
  2. byName:该选项能够根据bean名称设置依赖关系。当向一个bean中自动装配一个属性时,容器将根据bean的名称自动在在配置文件中查询一个匹配的bean。若是找到的话,就装配这个属性,若是没找到的话就报错。
  3. byType:该选项能够根据bean类型设置依赖关系。当向一个bean中自动装配一个属性时,容器将根据bean的类型自动在在配置文件中查询一个匹配的bean。若是找到的话,就装配这个属性,若是没找到的话就报错。
  4. constructor:造器的自动装配和byType模式相似,可是仅仅适用于与有构造器相同参数的bean,若是在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常。
  5. autodetect:该模式自动探测使用构造器自动装配或者byType自动装配。首先,首先会尝试找合适的带参数的构造器,若是找到的话就是用构造器自动装配,若是在bean内部没有找到相应的构造器或者是无参构造器,容器就会自动选择byTpe的自动装配方式。

210. 1八、如何开启基于注解的自动装配?

要使用 @Autowired,须要注册 AutowiredAnnotationBeanPostProcessor,能够有如下两种方式来实现:

一、引入配置文件中的<bean>下引入 <context:annotation-config>

 

211. 1九、请举例解释@Required注解?

在产品级别的应用中,IoC容器可能声明了数十万了bean,bean与bean之间有着复杂的依赖关系。设值注解方法的短板之一就是验证全部的属性是否被注解是一项十分困难的操做。能够经过在<bean>中设置“dependency-check”来解决这个问题。

在应用程序的生命周期中,你可能不大愿意花时间在验证全部bean的属性是否按照上下文文件正确配置。或者你宁肯验证某个bean的特定属性是否被正确的设置。即便是用“dependency-check”属性也不能很好的解决这个问题,在这种状况下,你须要使用@Required 注解。

须要用以下的方式使用来标明bean的设值方法。

RequiredAnnotationBeanPostProcessorSpring中的后置处理用来验证被@Required 注解的bean属性是否被正确的设置了。在使用RequiredAnnotationBeanPostProcesso来验证bean属性以前,首先要在IoC容器中对其进行注册:

[html] view plain copy

  1. <bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />    

可是若是没有属性被用 @Required 注解过的话,后置处理器会抛出一个BeanInitializationException 异常。

212. 20、请举例解释@Autowired注解?

@Autowired注解对自动装配什么时候何处被实现提供了更多细粒度的控制。@Autowired注解能够像@Required注解、构造器同样被用于在bean的设值方法上自动装配bean的属性,一个参数或者带有任意名称或带有多个参数的方法。

好比,能够在设值方法上使用@Autowired注解来替代配置文件中的 <property>元素。当Spring容器在setter方法上找到@Autowired注解时,会尝试用byType 自动装配。

固然咱们也能够在构造方法上使用@Autowired 注解。带有@Autowired 注解的构造方法意味着在建立一个bean时将会被自动装配,即使在配置文件中使用<constructor-arg> 元素。

 

213. 2一、请举例说明@Qualifier注解?

@Qualifier注解意味着能够在被标注bean的字段上能够自动装配。Qualifier注解能够用来取消Spring不能取消的bean应用。

下面的示例将会在Customer的person属性中自动装配person的值。

[java] view plain copy

  1. public class Customer{    
  2. @Autowired    
  3. private Person person;    
  4. }   

下面咱们要在配置文件中来配置Person类。

Spring会知道要自动装配哪一个person bean么?不会的,可是运行上面的示例时,会抛出下面的异常:

[html] view plain copy

  1. Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:    
  2. No unique bean of type [com.howtodoinjava.common.Person] is defined:    
  3. expected single matching bean but found 2: [personA, personB]    

要解决上面的问题,须要使用 @Quanlifier注解来告诉Spring容器要装配哪一个bean:

[java] view plain copy

  1. public class Customer{    
  2. @Autowired    
  3. @Qualifier("personA")    
  4. private Person person;    
  5. }  

 

214. 2二、构造方法注入和设值注入有什么区别?

请注意如下明显的区别:

  1. 在设值注入方法支持大部分的依赖注入,若是咱们仅须要注入int、string和long型的变量,咱们不要用设值的方法注入。对于基本类型,若是咱们没有注入的话,能够为基本类型设置默认值。在构造方法注入不支持大部分的依赖注入,由于在调用构造方法中必须传入正确的构造参数,不然的话为报错。
  2. 设值注入不会重写构造方法的值。若是咱们对同一个变量同时使用了构造方法注入又使用了设置方法注入的话,那么构造方法将不能覆盖由设值方法注入的值。很明显,由于构造方法尽在对象被建立时调用。
  3. 在使用设值注入时有可能还不能保证某种依赖是否已经被注入,也就是说这时对象的依赖关系有多是不完整的。而在另外一种状况下,构造器注入则不容许生成依赖关系不完整的对象。
  4. 在设值注入时若是对象A和对象B互相依赖,在建立对象A时Spring会抛出sObjectCurrentlyInCreationException异常,由于在B对象被建立以前A对象是不能被建立的,反之亦然。因此Spring用设值注入的方法解决了循环依赖的问题,因对象的设值方法是在对象被建立以前被调用的。

215. 2三、Spring框架中有哪些不一样类型的事件?

Spring的ApplicationContext 提供了支持事件和代码中监听器的功能。

咱们能够建立bean用来监听在ApplicationContext 中发布的事件。ApplicationEvent类和在ApplicationContext接口中处理的事件,若是一个bean实现了ApplicationListener接口,当一个ApplicationEvent 被发布之后,bean会自动被通知。

 

Spring 提供了如下5中标准的事件:

  1. 上下文更新事件(ContextRefreshedEvent):该事件会在ApplicationContext被初始化或者更新时发布。也能够在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。
  2. 上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()方法开始/从新开始容器时触发该事件。
  3. 上下文中止事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的Stop()方法中止容器时触发该事件。
  4. 上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的全部单例Bean都被销毁。
  5. 请求处理事件(RequestHandledEvent):在Web应用中,当一个http请求(request)结束触发该事件。

除了上面介绍的事件之外,还能够经过扩展ApplicationEvent 类来开发自定义的事件。

为了监听这个事件,还须要建立一个监听器:


以后经过applicationContext接口的publishEvent()方法来发布自定义事件。

[java] view plain copy

  1. CustomApplicationEvent customEvent = new CustomApplicationEvent(applicationContext, "Test message");    
  2. applicationContext.publishEvent(customEvent);    

 

216. 2四、FileSystemResource和ClassPathResource有何区别?

在FileSystemResource 中须要给出spring-config.xml文件在你项目中的相对路径或者绝对路径。在ClassPathResourcespring会在ClassPath中自动搜寻配置文件,因此要把ClassPathResource 文件放在ClassPath下。

若是将spring-config.xml保存在了src文件夹下的话,只需给出配置文件的名称便可,由于src文件夹是默认。

简而言之,ClassPathResource在环境变量中读取配置文件,FileSystemResource在配置文件中读取配置文件。

217. 2五、Spring 框架中都用到了哪些设计模式?

Spring框架中使用到了大量的设计模式,下面列举了比较有表明性的:

  • 代理模式—在AOP和remoting中被用的比较多。
  • 单例模式—在spring配置文件中定义的bean默认为单例模式。
  • 模板方法—用来解决代码重复的问题。好比. RestTemplate, JmsTemplate, JpaTemplate。
  • 前端控制器—Spring提供了DispatcherServlet来对请求进行分发。
  • 视图帮助(View Helper )—Spring提供了一系列的JSP标签,高效宏来辅助将分散的代码整合在视图里。
  • 依赖注入—贯穿于BeanFactory / ApplicationContext接口的核心理念。
  • 工厂模式—BeanFactory用来建立对象的实例。

转至:http://blog.csdn.net/lovesomnus/article/details/46470255

相关文章
相关标签/搜索