美文网首页
牛客网面经积累

牛客网面经积累

作者: _Kantin | 来源:发表于2017-08-10 10:57 被阅读87次

    1.Tomcat的总体结构及其工作原理

    https://www.ibm.com/developerworks/cn/java/j-lo-tomcat1/

    Tomcat 的总体结构

    clipboard.png

    Tomcat 的心脏是两个组件:Connector [kə'nektə(r)] 和 Container [kən'teɪnə],Connector 主要负责对外交流,可以有多个。Container 主要处理 Connector 接受的请求,主要是处理内部事务,只有一个。 Service将Connector 和 Container连接起来,用Lifecycle 接口来控制下面组件的生命周期,
    最外层的Server 提供一个接口让其它程序能够访问到这个 Service 集合、同时要维护它所包含的所有 Service 的生命周期,包括如何初始化、如何结束服务、如何找到别人要访问的 Service。

    二、Tomcat目录

    tomcat
    |---bin Tomcat:存放启动和关闭tomcat脚本;
    |---confTomcat:存放不同的配置文件(server.xml和web.xml);
    |---doc:存放Tomcat文档;
    |---lib/japser/common:存放Tomcat运行需要的库文件(JARS);
    |---logs:存放Tomcat执行时的LOG文件;
    |---src:存放Tomcat的源代码;
    |---webapps:Tomcat的主要Web发布目录(包括应用程序示例);
    |---work:存放jsp编译后产生的class文件;

    三、server.xml配置简介:

    下面讲述这个文件中的基本配置信息,更具体的配置信息请参考tomcat的文档:
    server: 1、port 指定一个端口,这个端口负责监听关闭tomcat的请求
    2、shutdown 指定向端口发送的命令字符串
    service: 1、name 指定service的名字
    Connector (表示客户端和service之间的连接):
    1、port 指定服务器端要创建的端口号,并在这个断口监听来自客户端的请求
    2、minProcessors 服务器启动时创建的处理请求的线程数
    3、maxProcessors 最大可以创建的处理请求的线程数
    4、enableLookups 如果为true,则可以通过调用request.getRemoteHost()进行DNS查
    询来得到远程客户端的实际主机名,若为false则不进行DNS查询,而是返回其ip地址
    5、redirectPort 指定服务器正在处理http请求时收到了一个SSL传输请求后重定向的端口号
    6、acceptCount 指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理
    队列中的请求数,超过这个数的请求将不予处理
    7、connectionTimeout 指定超时的时间数(以毫秒为单位)
    Engine(表示指定service中的请求处理机,接收和处理来自Connector的请求):
    1、defaultHost 指定缺省的处理请求的主机名,它至少与其中的一个host元素的name属性值是一样的
    Context (表示一个web应用程序):
    1、docBase 应用程序的路径或者是WAR文件存放的路径
    2、path 表示此web应用程序的url的前缀,这样请求的url为http://localhost:8080/path/****
    3、reloadable 这个属性非常重要,如果为true,则tomcat会自动检测应用程序的/WEB-INF/lib 和/WEB-INF/classes目录的变化,自动装载新的应用程序,我们可以在不重起tomcat的情况下改变应用程序
    host (表示一个虚拟主机):
    1、name 指定主机名
    2、appBase 应用程序基本目录,即存放应用程序的目录
    3、unpackWARs 如果为true,则tomcat会自动将WAR文件解压,否则不解压,直接
    从WAR文件中运行应用程序
    Logger (表示日志,调试和错误信息):
    1、className 指定logger使用的类名,此类必须实现org.apache.catalina.Logger 接口
    2、prefix 指定log文件的前缀
    3、suffix 指定log文件的后缀
    4、timestamp 如果为true,则log文件名中要加入时间,如下例:localhost_log.2001-10-04.txt
    Realm (表示存放用户名,密码及role的数据库):
    1、className 指定Realm使用的类名,此类必须实现org.apache.catalina.Realm接口
    Valve (功能与Logger差不多,其prefix和suffix属性解释和Logger 中的一样):
    1、className 指定Valve使用的类名,如用org.apache.catalina.valves.AccessLogValve类可以记录应用程序的访问信息
    directory(指定log文件存放的位置):
    1、pattern 有两个值,common方式记录远程主机名或ip地址,用户名,日期,第一行请求的字符串,HTTP响应代码,发送的字节数。combined方式比common方式记录的值更多

    2.ConcurrentHashMap原理分析

    通过分析Hashtable(线程安全)就知道,synchronized是针对整张Hash表的,即每次锁住整张表让线程独占,ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术。它使用了多个锁来控制对hash表的不同部分进行的修改。ConcurrentHashMap内部使用段(Segment) ['segm(ə)nt]来表示这些不同的部分,每个段其实就是一个小的hash table,它们有自己的锁。只要多个修改操作发生在不同的段上,它们就可以并发进行。
    有些方法需要跨段,比如size()和containsValue(),它们可能需要锁定整个表而而不仅仅是某个段,这需要按顺序锁定所有段,操作完毕后,又按顺序释放所有段的锁。这里“按顺序”是很重要的,否则极有可能出现死锁,在ConcurrentHashMap内部,段数组是final的,并且其成员变量实际上也是final的,但是,仅仅是将数组声明为final的并不保证数组成员也是final的,这需要实现上的保证。这可以确保不会出现死锁,因为获得锁的顺序是固定的。

    3.内存溢出和内存泄漏的区别

    内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出(内存不足)。
    内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光(申请到的内存不释放,占据系统内存)。
    memory leak会最终会导致out of memory!

    4.Java反射机制

    Java反射机制是一个反编译的过程.class-->.java。通过反射机制访问java对象的属性,方法,构造方法等;最经典的应用就是jdbc时用过一行代码, Class.forName("com.mysql.jdbc.Driver.class").newInstance();但是那时候只知道那行代码是生成 驱动对象实例,很多开框架都用到反射机制,hibernate、struts都是用反射机制实现的。

    5.在springMVC中,controller是单例的,那么当并发请求的时候,怎么处理?

    由于只有一个Controller的instance,当多个线程同时调用它的时候,它里面的instance变量就不是线程安全的了,会发生窜数据的问题。、
    1、在控制器中不使用实例变量
    2、将控制器的作用域从单例改为原型,即在spring配置文件Controller中声明
    scope="prototype",每次都创建新的controller
    3、在Controller中使用ThreadLocal变量

    6.线程池的底层实现原理

    worker:工作类,一个worker代表启动了一个线程,它启动后会循环执行workQueue里面的所有任务
    workQueue:任务队列,用于存放待执行的任务
    keepAliveTime:线程活动保持时间,线程池的工作线程空闲后,保持存活的时间。

    线程池原理:预先启动一些线程,线程无限循环从任务队列中获取一个任务进行执行,直到线程池被关闭。如果某个线程因为执行某个任务发生异常而终止,那么重新创建一个新的线程而已。如此反复。

    7.Java内存机制哪里不会出现内存溢出

    五大内存区域,除了程序计数器,其它的都会出现溢出:包括Java虚拟机栈与本地方法栈,方法区内存溢出,堆内存的溢出

    8.ArrayList和LinkedList的大致区别

    1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
    2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
    3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。

    9.关于Java的锁分类

    公平锁/非公平锁
    公平锁是指多个线程按照申请锁的顺序来获取锁。
    非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。有可能,会造成优先级反转或者饥饿现象。
    对于Java ReentrantLock而言,通过构造函数指定该锁是否是公平锁,默认是非公平锁。非公平锁的优点在于吞吐量比公平锁大。
    对于Synchronized而言,也是一种非公平锁。由于其并不像ReentrantLock是通过AQS的来实现线程调度,所以并没有任何办法使其变成公平锁。

    自旋锁
    在Java中,自旋锁是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU。

    10.BIO和NIO的区别

    BIO(Blocking IO)阻塞IO
    NIO(Non-Blocking IO)非阻塞IO
    共同点:两者都是同步操作。即必须先进行IO操作后才能进行下一步操作。
    不同点:BIO多线程对某资源进行IO操作时会出现阻塞,即一个线程进行IO操作完才会通知另外的IO操作线程,必须等待。
    NIO多线程对某资源进行IO操作时会把资源先操作至内存缓冲区。然后询问是否IO操作就绪,是则进行IO操作,否则进行下一步操作,然后不断的轮询是否IO操作就绪,直到iIO操作就绪后进行相关操作。

    11.JAVA中同步和异步的区别

    ArrayList 和HashMap是异步,Vector和HashTable是同步,这里同步是线程安全的,异步不是线程安全的。线程安全的并发时会在程序上加上锁,而其它非线程安全的则不会。

    12.缓存一致性

    缓存一致性机制整体来说,是当某块CPU对缓存中的数据进行操作了之后,就通知其他CPU放弃储存在它们内部的缓存,或者从主内存中重新读取。
    java语言中的volatile关键字就干了一件这样的事。使用volatile修饰的共享变量,当有线程修改了他的值的时候,他会立即强制将修改的值写回到主存,并通知其他使用该共享变量的线程:他们的缓存区中关于此变量的值已经失效。请重新从主存中读取。 但是volatile仅仅保证了可见性,关于i++的操作是原子性的操作,这个volatile保证不了。

    13.Java堆的插入和删除的过程

    ⑴最大堆的插入
    由于需要维持完全二叉树的形态,需要先将要插入的结点x放在最底层的最右边,插入后满 足完全二叉树的特点;然后把x依次向上调整到合适位置满足堆的性质, 时间:O(logn)。 “结点上浮”

    ⑵删除
    操作原理是:当删除节点的数值时,原来的位置就会出现一个孔,填充这个孔的方法就是, 把最后的叶子的值赋给该孔并下调到合适位置,最后把该叶子删除。“结点下沉”

    14.Java IO 中涉及到的设计模式

    装饰者模式:动态地将责任附加到对象上,若要扩展功能,装饰者模提供了比继承更有弹性的替代方案。
    通俗的解释:装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例。例如:根据inputstream和outputstream来扩展出很多其它的类。

    15.CopyOnWriteArrayList的工作原理

    其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改,这是一种延时懒惰策略。CopyOnWriteArrayList对add()操作还是加锁的,适合与读多写少的场合

    16.实践中如何实现SQL的优化

    ① SQL语句及索引的优化
    ② 数据库表结构的优化
    ③ 系统配置的优化
    ④ 硬件的优化
    具体优化的内容可以参考自己写的笔记。

    17. 什么情况下设置了索引但无法使用

    ① 以“%”开头的LIKE语句,模糊匹配
    ② OR语句前后没有同时使用索引
    ③ 数据类型出现隐式转化(如varchar不加单引号的话可能会自动转换为int型)

    18.索引的底层实现原理和优化

    B+树,经过优化的B+树
    主要是在所有的叶子结点中增加了指向下一个叶子节点的指针,因此InnoDB建议为大部分表使用默认自增的主键作为主索引。

    19.如何设计一个高并发的系统

    ① 数据库的优化,包括合理的事务隔离级别、SQL语句优化、索引的优化
    ② 使用缓存,尽量减少数据库 IO
    ③ 分布式数据库、分布式缓存
    ④ 服务器的负载均衡

    20.锁的优化策略

    ① 读写分离
    ② 分段加锁
    ③ 减少锁持有的时间
    ④ 多个线程尽量以相同的顺序去获取资源

    相关文章

      网友评论

          本文标题:牛客网面经积累

          本文链接:https://www.haomeiwen.com/subject/ruthrxtx.html