常遇面试题
不同的面试官问的问题不一样,侧重点不一样。并不是下面的都会问,可能还会问其他的,仅供参考。这些问题一般会结合一些场景来问,不过下面是大致问过比较多的一些。
Java基础:
面向对象的特点
面向对象主要有四大特征
- 抽象:将一些多个对象的共同特点进行找出来,然后抽象出来一个类或者方法。例如人类和狗都是动物,那么他们都有移动的功能,只不过移动的方式不同而已。在项目中一般抽象出来最多的是接口与方法
- 继承:对象的一个新生可以从现有的类中派生,这个过程成为类继承。子类拥有父类的所有非私有方法,并且执行顺序为:父类静态代码块、子类静态代码块、父类构造方法、子类构造方法。显示世界中也有继承,如:子女继承父类的遗产等。
- 封装:是面向对象的特征之一,1、主要是为了将数据隐藏,提供特定的方法进行调用,保护了模块的独立性2、方便传输或者保证传输过程的一致性,如项项目中常将页面信息封装成一个VO对象传递到Dao层。在实际过程中属相设为私有,方法设为protected,数据封装成对象都是一种表现形式
- 多态性:允许不同类的对象对同一信息作出相应,李彤同样选择了编辑-粘贴操作,在字处理程序和绘图程序中有不同效果。同样是查询操作,在查询个人信息与查询学生课程信息会显示不同的信息
面向对象在程序设计过程中首先设计的是对象,然后再考虑对象之间的关系,例如:老师添加学生信息,首先应该有两个对象:学生、老师,然后在老师对象中有添加学生的功能
抽象类与接口的区别
一个是用abstract修饰、一个是interface修饰
抽象类拥有构造方法、接口没有构造方法
抽象类能拥有方法的实现,接口不能有方法的实现
抽象类被继承需要重写里面所有的抽象方法,接口被实现必须实现所有方法
抽象类里面的方法类型可以是public、protected方法,接口必须是public方法
抽象可以包含静态方法、接口不能包含静态方法
一个类可以实现多个接口,但只能直接继承一个抽象类
说说final
中文为:最终的、最后的
可以用来修饰局部变量、类属性、形参、方法、类
当final修饰类是,该类为最终类,不可以被继承
当final修饰方法是,为最终方法,不能被重写
当final修饰变量是,该变量的引用不能被改变
当final修饰属性以及变量属性,必须进行进行初始化赋值
Static的用法
用static修饰的方法为静态方法,静态方法只能引用静态的全局属性,静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法中不能使用this和super关键字
使用static修饰的变量叫做静态变量或者类变量,存放在jvm里面的堆区,每次创建一个类对象,都是访问同一个类变量
静态方法块,在每次实例化这个类,静态方法块首先被加载。并且只能被加载一次
==与equals的区别:java中所有的非基本数据类型,存放的值都是对象的引用
Java分为基础类型分为两类:一个是基本数据类型、一个是复合数据类型
基本类型用==比较的是他们的值
当他们用==比较复合数据类型时,比较的是他们存放的地址,除非是同一个new出来的对象,他们比较够的对象为true,否则比较结果结果为false 如String,Integer,Date在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了
对于复合数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是基于他们在内存中的存放位置的地址值的
重载与重写的区别
方法重载是让类以同一的方式处理不同类型的一种手段,是多态的一种表现;重写用于父类与子类之间,子类不适应父类的方法,需要在子类中重新定义一个方法
重载方法时候,方法参数类型与长度不一样,也可以返回值不同,但是不能与返回值类型来区分。重写方法是参数类型与长度和返回值必须一样
String,stringBulider与stringBuffer的区别
首先String是常量,对象不可变;StringBuffer与StringBuilder是继承AbstractStringBuilder类,对象可变
String是常量,所以线程安全;StringBuffer对方法加了同步锁,所以也是线程安全;StringBuilder并没有对方法加同步锁,所以是非线程安全的
因为StringBuilder没有加同步锁,所以效率高于StringBuffer
String对象的创建
String s = new String(“abc”),如果在java方法区的常量池中没有“abc”对象,则会创建三个对象,其中s作为对象的引用会在栈区开辟一个空间,类型为String类型,new String(“abc”)则会在堆区创建一个空间,用于存放“abc”的引用地址,真正用于保存“abc”字符串的空间在方法区的常量池中
Object类有哪些方法
toString、wait、equals、getClass、notify、notifyAll、hashCode
异常有哪些?举几个例子
RuntimeException:NullPointException异常
ReflectiveOperationException:ClassNotFundException异常
InterruptedException:当一个线程正在处于等待、休眠等状态被打断时,抛出的异常
Throw与throws的区别
Throw是明确在哪个地方抛出的哪个异常,throws是告诉程序这个方法可能抛出的那几个异常,方法调用者需要对这些异常进行处理
Throw语句是在方法体内,表示抛出异常,由方法体内的语句处理
Throws语句在方法声明后面,表示再抛出异常,由该方法调用者来处理
ArrayList与LinkedList的区别
ArrayList是基于动态数组的数据结构、LinkedList基于链表的数据结构
随机访问ArrayList效率高于LinkList,但是若是单条的新增与删除效率高于LinkList,但是批量的删除、新增效率低于LinkList,做了测试,如果用两个list集合添加1000000数据,并且每条数据只存一个值,那么两个相差不大;测试结果为150ms左右与125ms左右,但是如果每条数据为两个值:list.add(1,null);那么ArrayList为100ms左右,LinkedList数据为20ms左右
HashMap,Hashtable和HashSet的区别(只要问了集合都会问到)
HashSet底层采用的是HashMap进行实现的,但是没有HashMap中的value,HashSet不容许重复对象
Hashtable是基于Dictionary类的,而HashMap是基于Map接口的一个实现
Hashtable里默认的方法是同步的,而HashMap则是非同步的,所以HashTable是多线程安全的
HashMap可以将key设置为null,但是只能有一个,而value可以有多个null.但是Hashtable不能有null
HashMap的初始化大小为16,并且扩容方式为超过长度的75%,增加一倍;Hashtable的初始化大小为11,超过长度的75%,扩容方式为2*size+1
HashTable、HashMap、HashSet都是迭代器快速失败的集合,也就是在创建Iterator之后,如果是不使用iterator的remove方法,而是使用其他方法对HashTable进行修改,则会抛出ConcurrentModificationException
concurrentHashMap的实现原理
多线程
首先多线程是一中机制,它允许在程序中并发的执行多个指令流,每个指令流称为一个线程,在单核中,并发是指:在同一个时间段可以执行多个指令
在java中实现多线程的方法有两种,一个是继承Thread类,重写run()方法,第二是方法是实现Runnable接口,实现run()方法
线程有5个状态,分别是:新建、就绪、运行、阻塞、死亡,其中在java中新建就是new出一个线程,就绪就是调用了start方法,运行就是执行了这个线程、阻塞就是这个线程被挂起、死亡就是线程运行完毕
线程同步,同一个进程的多个线程共享同一片存储空间,容易造成数据的混乱,而synchronized关键字可以解决这个问题,包括synchronized 方法和synchronized 代码块
synchronized 方法会大大的影响效率,所以一个加了锁的方法最好的设计成最简单的实现,一些不能引起数据混乱的操作可以放在方法外面
对于一些访问类成员变量的代码最好可以放在synchronized块中,这样可以很大的提高效率
Java采用采用同步机制来保障多个线程对共享资源的访问不能真正的满足需求,因为在任意时刻需要的资源部一定都准备好,同一时刻准备好的资源也不止有一个,所以java采用了线程的阻塞,例如sleep()方法,有相应的唤醒机制,如:notity方法
什么叫多线程的可见性和有序性
可见性:多个线程之间是不能互相传递数据通信的,它们之间的沟通只能通过共享变量来进行。Java内存模型(JMM)规定了jvm有主内存。主内存是多个线程共享的。当new一个对象的时候,也是被分配在主内存中,每个线程都有自己的工作内存,工作内存存储了主存的某些对象的副本,当然线程的工作内存大小是有限的
有序性:线程在引用变量时不能直接从主内存中引用,如果线程工作空间中没有该变量,则会从主内存中拷贝一个副本到工作空间内,这个过程为read-load,完成后线程会引用该副本。如果同一线程再度引用该字段时,有可能重新从主内存中获取变量副本,也有可能直接引用原来的副本,也就是说read、load、use顺序可以有JVM实现系统决定
怎么使用锁,以及锁之间怎么运行
理论上,每一个对象都可以作为锁,但是一个对象作为锁时,应该被多个线程共享,这样才显得有意义
每个锁对象都有两个队列,一个是就绪队列,一个是阻塞队列,就绪队列存储了被阻塞的线程,当一个线程被唤醒后,才会进入到就绪队列,等待CPU的调度
一个线程执行临界区代码过程如下
获取同步锁
清空工作空间
从主存拷贝变量副本到工作空间
对这些变量计算
将变量从工作内存写回到主存
释放锁
怎么保证线程之间的安全通讯的问题
Synchronized关键字:作为线程并发环境的执行有序性的保证手段之一,当一段代码会修改共享变量,这一段代码成为互斥去或者临界区,为保证共享变量的正确性,synchronized标示了临界区
Volatile关键字:是java提供的一种同步手段,只不过它是轻量级的同步,因为volatile只能保证多线程的内存可见性,不能保证多线程的执行有序性
Sychronized方法和sychronized块
sychronized块的特性
当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内是能有一个线程执行
当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块
当一个线程访问object中的synchronized(this)同步代码块时,其他线程访问object中所有其他synchronized(this)同步代码块的访问将被阻塞
各种锁之间的执行关系
一个类中所有synchronized方法,在争取获取该对象锁时形成互斥
一个类中的synchronized方法与非synchronized方法之间不会形成互斥
一个类中的使用一个类的字节码为为对象锁,与synchronized方法不会形成互斥
GC
对于每个对象而言,垃圾回收机制分为两个阶段:finalization和reclamation,其中finalization指运行这个对象的finalize方法
GC的过程的基本步骤1、首先确定这个对象是不可达的,其次,如果对象有finalize方法,那么对象被添加到finalization队列中,然后在某个时间点finalize方法,用于释放finalize中的资源,最后,回收对象占用的内存
对象的引用类型
StrongReference:强引用类型的引用,如果一个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回收它。当内存空 间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题
SoftReference:被这种引用指向的对象,如果没有被其他Strong Reference引用的话,在任何时候都可能被GC.通常在可用内存较低或者在抛出outOfMemeoryError之前被GC,适合实现Cache
WeakReference,如果没有SoftReference和StrongReference引用时,立即会被GC,和SoftReference的区别是:WeakReference对象是被eagerly collected,即一旦没任何SoftReference和StrongReference引用的对象,立即被程序了解
PhantomReference(幻影引用):当没有StrongReference、SoftReference和WeakReference引用时,随时被GC,通常和ReferenceQuere联合使用,管理和清除与被引用对象相关的本地资源,没有finalize方法
进程与线程的区别
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,线程是进程的一个实体,是CPU调度和分派的基本单位:如开一个QQ程序相当于开了一个进程,你在QQ里面与多人聊天相当于开了多个线程
进程与线程的主要差别在于它们是不同的操作系统资源管理方法。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其他的进程产生影响,而线程只是一个进程中的不同执行路径,一个线程死掉了就等于整个线程死掉,所以多进程的程序比多线程的程序健壮,但是进程却换时、耗费资源大,效率要差一点
一个程序只有一个进程,一个进程至少有一个线程
进程有一个程序运行的入口、顺序执行序列和程序的出口,但是线程不能独立运行,必须依存在应用程序中,有应用程序提供多个线程执行控制
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源的分配
线程执行开销小,但不利于资源的管理和保护,而进程相反,同时,线程适应于在smp机器上运行,而进程可以跨机器运行
JSP:
9大内置对象
Page对象代表JSP本身,更准确地说它代表JSP被转移servlet,它可以调用servlet类所定义的方法,page对象在jsp程序中的应用不是很广泛,生命周期在当前页面有效
Config对象是在一个servlet程序初始化时,jsp引擎向它传递消息用的,此消息包括servlet程序初始化时需要的参数及服务器的有关信息,config对象其实是现实javax.servlet.ServletConfig接口的类的实例对象。在服务器启动的时候就创建,服务器关闭时销毁
其中有servletConfig接口,里面可以得到servelt初始化参数
还有一个FilterConfig接口,里面可以得到filter的初始化参数
Request对象可以获取客户端的输入信息,客户端的请求信息通过Http头和信息体传送到服务器端的,一个会话开始时被创建,这个请求被响应后销毁。一次请求是可以或多次传递的,主要方法有getParameter、getAtrribute、setAtrribute、getRequestDispatcher().forword(),getServlet()、getServletContext()
Response代表的是对客户端的响应,主要是将jsp容器处理过的对象传回到客户端,生命周期和request一样,主要用于页面转发,重定向
Session对象是十分重要的一个jsp内置对象,它可以用来在每一个用户之间分别保存用户信息,当用户第一次访问jsp组件或者服务器时,服务器需要为客户端的请求创建一个session,先会检查请求中是否包含session id,如果包含,那么就从服务器内存中取出session,没有则会创建。如果没有设置关闭时间,默认session的不活动时间为30分钟,你也可以在web.xml中配置session的活动时间设置时间。访问html不会被创建。一般用于记录用户的个人信息,经常用于判断是否登入过滤等功能。
Application对象可将信息保存在服务器中,直到服务器关闭,否则application对象中保存的信息会在整个应用中都有效,与session对象相比,application对象的生命周期更长,相当于系统的全局变量,当服务器启动启动就会被创建,直到服务器关闭被销毁
Out对象用于在web浏览器输出信息,并且管理应用服务器上的输出缓冲区,在使用out对象输出数据时,可以对数据缓冲区进行操作,及时清除缓冲区的残余数据,为其他的输出让出缓冲空间,待数据输出完毕后,要及时关闭输出流
pageContext对象的作用是取得任何范围的参数,也可以获取jsp页面的out、request、response、session、application等对象,pageContext对象的创建和初始化都是由容器来完成
Exception对象是现实异常信息,只有在包含isErrorPage=“true”的页面中才能被使用
几大作用域
Application,在所有应用程序中有效:从应用启动到应用结束
Session在当前会话中有效
如果存在一个cookie,里面存在session_id,然后从服务器的session里面得到session_id和cookie里面的session_id进行对比,如果有相同则session不是新的
如果cookie里面没有得到session_id,或者session_id与服务器里面的session并不相同,服务器则创建新的session,然后将session放在response里面,设置到cookie里面存在客户端中,供下次判断做存储
Request在当前请求中有效
Page在当前页面有效
Servlet的生命周期
Servlet的工作过程:
在客户端对web服务器发出请求
Web服务器接受请求后将其发送给servlet
Servlet容器为此产生一个实例对象并调用servelt的方法对客户端Http请求进行处理,然后将处理的结果返回给web服务器器
Web服务器从servlet实例中结果到响应发送给客户端
Servlet的生命周期可以分为四个阶段:实例阶段、初始化阶段、服务器阶段、实例销毁阶段
创建servlet实例,在默认情况下servlet实例是在第一个请求到来的时候创建,如果有的servlet需要复杂的操作,可以在web.xml中配置,这样可以在服务器启动时候就可以创建实例
一旦servlet实例被创建、web服务器会自动调用init方法来初始化,config包含了servlet的配置信息
一旦servlet实例成功创建及初始化,该servlet实例就可以被服务器用来服务于客户端的请求并生成响应
当web服务器认为servlet实例没有存在的必要了,比如应用重新装载或者服务器关闭,以及servlet很长时间没有被访问过,服务器可以从内存中销毁该实例
Servlet的作用
创建并返回一个基于客户端请求性质的动态内容的完整的html页面
创建可嵌入到现有的html页面中的一部分html页面
与其他服务器资源进行通信
运行在服务器端的程序,用于处理及响应客户端的请求
Servlet与jsp的区别
Jsp在本质上就是servlet,但是两者的创建方式不一样
Servlet完全java程序代码构成,擅长于流程控制和事务处理,通过servlet来生成动态页面很不直观
Jsp由html代码和jsp标签构成
Jsp编译后是servlet类
Post请求与get请求的区别
Get从指定的服务器中获取数据,post提交数据给指定的服务器处理
使用get方法时,页面信息会显示在url地址后面,对于数据安全性不利;使用post方法时,请求信息单独存在,和http请求一起发送给服务器,利于数据安全
Get请求被够被缓存,post请求不能够被缓存
Get请求会保存在浏览器的浏览器记录中,post请求不会保存在浏览器的记录中
Get请求的url能够保存为浏览器书签,post的无法保存在书签中
Get请求有长度限制,post请求没有长度限制
点击返回、刷新按钮,get没有影响,post请求数据会重新发送
http请求的过程
建立连接:客户端与服务器建立TCP连接
发送请求:打开一个连接后,客户端把请求信息发送到服务器的相应端口上,完成请求动作提交
发送响应:服务器在处理完客户端请求之后,要想客户端发送响应消息
关闭连接:客户端和服务器都可以关闭套接字来结束TCP/IP对话
http传输协议是无状态的,传输协议不记忆从一个请求消息到另一个请求消息的的任何信息(如果发生错误,这个请求不能转弯,需要再传一次并得到处理)
数据结构:
有哪些排序?在冒泡,选择,插入,快速及堆排序中任选一个重点问
冒泡排序:两两比较,由底至上地上升,将两者较小(较大)的升上去,最坏的情况下时间复杂度为O(n^2)
代码
冒泡排序的优化:通过设置一个标记变量,标记数列中的数是否在循环结果前就已经排好序,最好的情况下时间复杂度为O(n)
代码
选择排序的基本思路:没一趟从待排序的记录中选择关键字最小的记录,顺序放在已排好的子序列的最后,时间复杂度为O(n^2)
代码
堆排序思路:
创建初始堆:创建一个完全二叉树,保证所有的父节点都比它的孩子结点数值大
每次交换第一个和最后一个元素,输出最后一个元素(最大值),然后把剩下的重新调整为大根堆
叶子节点与子节点为2的关系
No = N2 +1 :在完全二叉树中,子节点=节点为2+1
在现实生活中哪里会用到队列,哪里会用到栈?
队列:买票、银行办理业务
栈:铁路调度用到了队列
数据库:
三大范式(举例子说明)
第一范式:属性不可分
第二范式:确保表中的每列都依赖主键
第三范式:确保每列都与主键是直接依赖
数据库的连接有哪些?有什么区别?
ODBC数据库连接:
是一种底层的访问技术,可以是客户应用程序程序从底层设置和控制数据库,完成一些高级数据库技术无法完成的功能,只使用与关系型数据库
MFC DAO
提供了一种通过程序代码创建和操纵的数据库的机制,是操作JET数据库时性能最好的技术接口之一,可以访问从文本文件到大型后台数据等多种数据格式
ADO
是基于OLE DB的访问接口,它是面向对象的OLE DB技术,继承了OLE DB的优点。属于数据库访问的高层接口
JDBC接口
按照ODBC的模式制定的,是一个通用底层、支持基本SQL功能的java API,使程序可以面对统一的数据库界面,无需考虑数据库的差异性
JDBC建立数据库连接的步骤
加载JDBC驱动程序
提供JDBC连接的URL
创建数据库的连接
创建一个Statement
执行SQL语句
处理接口
关闭JDBC对象
数据库的分页
定义每页显示的数目
前台传条目数过去
数据库索引(主索引,非聚集索引)
主索引有称集聚索引,该索引中键值的逻辑顺序决定了表中相应的物理顺序
应该定义的列越少越好
被连接访问的列,包含大量非重复值的列
使用>、<=等运算符的列
回大型结果集的查询
数据存储在一个地方,索引存储在另一个地方,索引带有指针指向数据的存储位置,这样表中信息按另一种顺序存储,定义索引的字段排好序
数据库的特性(ACID)
Atomicity原子性:事务中包含的程序要不一个都不执行,要不全部执行
Consistency一致性:事务执行之前和执行之后数据库必须处于一致性状态,如主外键的主键改变,想关联的外键也要改变
Isolation分离性:事务时相互隔离的,不能被其他事务所干扰
Durability持久性:当系统发生意外时,确保已提交的事务的更新不能丢失,对已提交的事务的更新能恢复
事务的模式
显示事务:就是用户使用T-SQL明确的定义事务
自动提交事务:自动提交事务时一种能够自动执行并能自动回滚的事务,例如删除主外键关联的主表、有外表存在!删除自动取消
隐式事务
数据库的事务处理(游标)
游标实际上是一种能从多条数据记录的结果集中每一次提取一条记录的机制
允许定位到结果集中的特定行
从结果集的当前位置检索一行或多行数据
支持对结果集中挡墙位置的行进行修改
游标的基本操作
定义游标、打开游标、循环读取游标、关闭游标、删除游标
数据库连接池
对于共享数据的一个著名的设计:资源池,该模式是为解决资源频繁分配、释放所造成的问题,数据库连接池的基本思想就是为数据库建立一个“缓冲池”,预先在缓冲池中放入一定数量的连接,当需要建立数据库连接是,只需要从缓冲池中取出一个,使用完毕后再放回去,我们可以通过设置连接池最大数来防止系统无尽的与数据库连接
相关问题的分析
并发处理:使用synchronized lock关键字保证线程同步
事务管理:我们需要保证一个事务独占一个连接来实现
连接池的分配与释放:要合理的分配和释放连接池,可以提高连接的复用性
连接池的配置与维护:我们应该设计多少个连接池才能使性能最佳,一般可以采用引用计数来判断设置多少个连接比较合适
PrepareStatement与Statement的区别
PreparedStatement对象不包含SQL语句,在大多数情况下这个SQL语句是已经编译好的,只需要替换事先定义好的变量,减少了与数据库的通讯。但是Statement每次运行SQL语句都需要重新编译,运行速度慢
Statement方法有createStatement所创建,对象只发送简单的SQL语句,PreparedStatement是由方法PrepareStatement所创建,对象用于发送带有一个或多个输入参数的SQL语句
计算机网络:
3次握手
建立TCP需要三次握手才能建立分别是:
客户端发送连接请求到服务器:Client端通过发送报文的形式请求连接
服务器授予客户端连接请求:通过ACK(Acknowledgement)报文回复客户端请求
客户端确认连接:接受到ACK(Acknowledgement)报文,并发送ACK报文给服务器这样就建立的连接
为什么TCP需要三次握手才能建立连接
第一次握手,能够证明客户端的发送器有用
第二次握手,能够证明服务器的接受器能够成功
第三次握手,能够证明服务器的发送器能够成功,客户端的接受器有用
四次挥手
断开TCP连接需要四次挥手,终端双方可以是任意一方,过程如下:
假设客户端发起了关闭连接请求,就发送FIN报文给服务器
如果服务器没有发送完数据就发送ACK报文告诉客户端我还没有准备好,客户端进入FIN_WAIE状态,如果服务器数据发送完毕,就发送FIN请求告诉客户端我准备好了
客户端接收到了FIN报文,再重新发送ACK报文确认服务器知道关闭,并进入TIME_WAIT状态,如果服务器没有接收到ACK则可以重新转
服务器接受到了ACK报文,就可以关闭连接,客户端等待了2MSL后没有接收到回复就自动断开
为什么TCP连接需要4次挥手
第一次挥手,说明客户端要断开连接了,客户端发送信息成功
第二次挥手,说明服务器接受成功,告诉客户端我接受到了你的请求,同意了你的要求
第三次挥手,说明客户端表示接受到了服务器的同意,服务器也知道了客户端知道了自己的同意
第四次挥手,说明客户端断开了连接,服务器也可以断开连接了
7层协议
第一层:物理层
透明传动比特流,设备包括集线器,发送器、接受器、电缆
第二层:数据链路层
接受网络层的数据帧并为物理层封装这些帧,并为物理层的原始数据封装成网络层的帧
分为介质访问控制和逻辑链路控制
网络层
确定数据包传送的目的地的路径
将大包分成小份的数据包
设备有:路由器、网桥路由器、网关
传输层
确保按顺序无错的发送数据包,把大量信息分成易于管理的包以便向网络发送
会话层
在分开的计算机的两种应用程序之间建立一种虚拟连接,这种虚拟连接称为会话
通过在数据流中设置检查点而保持应用程序之间的同步
允许应用程序进行通信的名称识别和安全性的工作
表示层
负责协议转换、数据编码、数据压缩
应用层
应用成层向应用进程展示所有的网络服务,当一个应用进程访问网络是,通过该层执行所有的动作
http协议
HTTP是一个属于应用层的面向对象的协议,由于其简捷、快捷的方式,适用于分布式超媒体信息系统
HTTP的主要特点
支持客户/服务器模式
简单快捷:客户端想服务器发送请求时,只需传送请求方法和路径。请求方法有GET、HEAD、POST
灵活,HTTP允许传输任意类型的数据对象
无连接:限制每次连接只处理一个请求
无状态:是指协议对于事务处理没有记忆能力,缺少状态意味着如果后续处理需要前面的信息,必须重传
HTTP的URL
URL用于定位网络资源的位置
HTTP的请求
请求分为三部分:请求行、消息报头、请求正文
GET:请求获取ReQuest-URL所标识的资源
阿里巴巴的面试题
如何判断一个字符串是否是回文
将自已字符串从中间切开,然后判断两边
使用StringBuffer的reverse方法
如果全是数字还可以用取余的方法与最高位进行比较
折半查找
必须有序
判断每次的中间数是否与需要查找的数相等
如果小于就取中间数下标+1,在与最后数下标相减,除于2
如果大于就取中间数下标-1,再与第一个数下标相减,除于2
如果等于则输出该数的下标
归并排序
将一个数组分成N分,然后在将N分系列进行排序
然后再两两合并N序列,在进行排序
如果得到一个完整的已经拍好序的序列
N的大小为总数/2
查找字符串(从一段字符串查找小字符串)的时间复杂度
KMP算法:http://blog.youkuaiyun.com/dazhong159/article/details/7971438
BM算http://www.cnblogs.com/whyandinside/archive/2012/06/03/2532651.html
三次握手
12(三次握手的解析)
为什么使用三次握手,而不是两次
第一次握手是告诉对象,我发送了请求
第二层握手是告诉对方我的接受器正常,并且你的发报器正常
第三次握手是告诉对方你的发报器也正常
通过这三次握手就能确定双方的发报器和接受器都正常
Nosql
泛指非关系型数据库
NoSsl数据库分为四大类
键值存储数据库:这一类数据库主要使用到一个哈希表,这个表中有一个特定的键与一个指针指向特定的数据
列存储数据库
通常用来应对分布式村粗的海量数据,键仍然存在,但是可以指向多个列
文档型数据库
该类型的数据模型是版本化的文档,半结构化的文档以特定的格式存储,而且文档型数据库比键值数据库的查询效率更高
图形数据库
它是使用灵活的图形模型,并且能够扩展到多个服务器上,没有标准的查询语句
使用情况:
数据模型比较简单
需要灵活性更强的IT系统
对数据库性能要求比较高
不需要高度的数据一致性
对于给定key,比较容易映射复杂的环境
效率比较
线程池
线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务
创建一个线程池,事先为程序可能需要的对象准备好,然后一旦程序需要就不用再创建,直接拿就行了
一旦用户不需要这个对象,则将这个对象放回到线程池中
1000000条广告设计权重
创建一个权重容器,将符合该权重的网页放在哪里去
然后将所有的权重值相加M
循环随机产生一个权重值N,用权重总数M-N
如果值小于等于0,则得到的N就是需要查找的权重
然后在该权重下随机得到一个网页
设计随机数
首先,在电脑程序中不可能产生一个真随机数(我在面试的时候,然后就懵逼了,一直在想怎么做),所以产生一个伪随机数
通过一系列时间来得到系统不可能得到相同的数字,如:点击鼠标的时间,产生随机数方法被调用的时间,用户的id,用户输入的随机数的范围等一些数字
将这些数字相加或者相减,然后在去mod
如果明天要交项目,但是不会做!你会怎么办
看到这个题目我也懵逼了,我想到的方法有三个
问大神
查文档
通宵加班
然后我实在想不出来,就问了HR,他说有没有想过找个相同功能的项目来代替,我心中一万个草泥马崩腾而过
hashMap如何实现的
底层采用数组和链表来实现对数据的存储,其中开始创建一个16长度的数组,用来保存容器个数!采用一个Entry(key、value、next)来保存map里面的值,采用链表来连接
通过计算hash值%hashmap.length来得到需要查找的数据
通过加载因子0.75来实现扩容2倍
不是线程安全的类,如果需要一个线程安全的集合,可以用Collections.synchronizedMap(HashMap)保证线程安全,也可以将这个类用concurrentHashMap类来代替
HashMap和concurrentHashMap的区别
hashMap是线程不安全的,concurrentHashMap是线程安全的
concurrentHashMap引入了一个“分段锁”的概念,把map分成了n个segment,put和get的时候,根据key.hashCode()算出放在哪个segment中
每个segment都采用Hashtable的形式保证线程安全
其中size方法需要会锁定全部的范围,这样就能够保证数据得到了正确的长度
如果你要修改那个segment的部分,就会在相应的segment加锁,其余的segment不会锁定,保证了数据实现了高并发、高可用
concurrentHashMap集合得到里面的信息是通过该key的hashcode得到的,也就是说,你要通过key查询,系统会通过key计算出hashcode,这样就能得到value
如果size()长度超过了int类型的最大长度,则返回int的最大长度。而不是进行越界返回
HashMap与hashTable的区别
Hashmap的方法是非线程同步的,hashtable是线程同步的
Hashmap的初始大小为16,扩容方式为2*n,hashtable的初始大小为11,扩容方式为2n+1
Hashmap允许存null,hashtable不允许存null
Hashmap直接重新计算对象的hashcode,而hashtable直接使用hashtable
Hashmap和hashtable都使用了iterrator,hashtable还使用了Enumeration的方式
HashTable采用的是synchronized方法进行加锁,公共方法都加了synchronized锁,其中entrySet()方法采用的是Collections.synchronizedSet()方法,这样就能返回一个安全的set
进程间通信有哪几种
共享存储器系统
基于共享数据结构的通讯方式:要求诸进程公用某些数据结构,借以实现诸进程的信息交换,适用于少量的数据,通讯效率低下
基于共享存储区的通讯方式:在内存中划出一块共享存储区域,诸进程可通过对该共享区的读或写交换信息,实施通信
管道通信系统
管道用于连接一个读进程和一个写进程以实现它们之间通讯的一个文件,又名pipe文件,提供以下三种协调能力
互斥:即当一个进程正在对pipe执行读/写操作室,其他进程必须等待
同步:当写入进程把一定数量的数据写入pipe,便去睡眠等待,知道读进程取走数据后再唤醒
确定对方是否存在,只有确定对方已存在时才能进行通信
消息传递系统
以格式化的信息为单位,将通信的数据封装到信息中,并利用操作系统提供的 一组通信命令,在进程之间进行通信,分为两类
直接通信方式:发送进程利用os提供的方式,直接把信息发送给目标进程
间接通信方式:发送和接受进行,通过共享中间实体(称为邮箱)的方式进行信息的发送和接受
客户机-服务器通信
在网络环境中的各种应用领域称为当前主流的通信实现机制,主要有三种实现方式(见操作系统69)
套接字
基于文件型
基于网络型
JVM分为哪些区,每一区都干什么
程序计数器:程序计数器是线程独立的,用于指向某个线程下一条待执行的指令地址
栈区:都是为方法执行服务的,线程独立,它的生命周期与线程相同
虚拟机栈:存储一些局部变量、动态链接、方法出口灯
本地方法栈:为java底层调用本地native方法服务的
堆区:
Java堆:存储的是java中所有对象的实例和数组,是虚拟机运行时内存最大的一块,也是垃圾回收的主要场所
方法区:包含一块叫做运行时常量池的区域,它主要存放的是在编译期间生产的各种字面量和符号引用,类加载时,这部分数据被加载到常量池中
Jvm如何GC,新生代、老年代、持久代都存储哪些东西
如何GC
确定对象不可达
如果对象有finalize方法,那么对象被添加到finalization队列中,在某个时刻调用finalize方法
回收内存
新生代、老年代、持久代都存储哪些东西
新生代:存放新生产的对象,新生代的目标是尽可能的快速的收集掉哪些生命周期短的对象
Eden区,两个survivor区,大部分对象在Eden区中生成,当Eden区满时,还存活的对象将被赋值到survivor区
如果新生代都满了,将对象复制到老年代
老年代:在年轻代中经历了N次垃圾回收后仍然存活的对象,就会保留在老年代中,存放一些生命周期较长的对象
持久代:用于存放静态文件,如java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,例如hibernate等
Scavenge GC
申请Eden空间失败时,就会触发Scavenge GC,主要是清除Eden区域中非存活的对象,并且把尚且存活的对象移动到Survivor区中
Full GC
对整个堆进行整理,包括young、tenured和perm.full GC因为需要对整个进行回收,所有要比Scavenge GC要慢,导致Full GC的条件是:1、老年代被写满2、持久代别被写满3、System.gc()被显示调4、上一次GC之后heap的各域分配策略动态变化
GC用的引用可达性分析算法中,有哪些对象可作为GC roots对象
GC判断一个对象是否可达有两种方式
引用计数算法:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器的值就加1,当引用失效时,计数器的值就减1,任何时刻的计数器为0的对象就是不可能再使用了:不能解决相互引用的问题
可达性分析算法:通过一系列的称谓“GC roots”的对象作为起始点,从这些节点开始向下搜索,搜索所有走过的路径为引用链,当一个对象到GC roots没有任何引用链项时,则证明此对象不可用
可以作GC roots对象可能有
虚拟机栈中引用的对象
方法区中类静态属性引用的对象
方法区中常亮引用的对象
本地方法栈中JNI(即一般说的native方法)引用的对象
TCP如何保证可靠传输
以字节为单位的滑动窗口:如A发送的窗口号为50,发送的报文大小为50,则B返回的号为100,否则就重传。如果来不急反应,可以先发送多条信息
缓存机制
发送应用程序传送给对方是TCP准备的数据
TCP已经发送但尚未收到确认的数据
超时重传的时间选择:TCP每发送一个报文段,就对这个报文段设置一次计时,如果超过重传时间还没有收到确认信息,则重传这个报文
选择确认SACK:若收到的报文无差错,知识未按序号,中间还缺少一些序号的数据,采用选择确认的方法来传送缺少的数据
TCP和UDP的区别
TCP全称:transmission control protocol(传输控制协议),UDP全称User Datagram Protocol(用户数据报协议)
Tcp是面向连接的协议,实际是在物理线上创建一条“虚拟通道”,这个链接只有等到断开连接(两个终端都会向对方发送一个FIN包:见四次挥手)的时候才会被释放
UDP协议:一样在物理线上创建一条虚拟通道,存储转发的形式进行数据传输。但是当UDP协议传送完数据后,这条虚拟通报立即被注销。无序、不可靠
操作系统什么情况会死锁
产生死锁的原因
竞争资源:当系统中多个进程使用共享资源,并且资源不足以满足需要,会引起进程对资源的竞争而产生死锁
进程间推进的顺序非法:请求和释放资源的顺序不当,也同样会产生进程死锁
产生死锁的必要条件
互斥条件:进程对所分配到的资源进行排它性使用,在一段时间内某资源只由一个进程占用
请求和保存条件:指一个进程已经保持了至少一个资源,但又提出新的资源请求,而此资源被其他占用,此时请求进程阻塞,但又不放弃已经占有的资源
不剥夺条件:进程已经获得资源,在未使用完之前,不能被剥夺,只能在使用完时,由进程自己释放
环路等待条件:发生死锁是,必然存在一个进程-资源的环形链
预防死锁
破坏产生死锁的四个必要条件
摒弃“请求和保存”条件
摒弃请求:当进程来时,一次性分配所有资源给这个进程
摒弃保存:当这个进程得不到资源分配,就不给这个进程分配其他资源
摒弃不剥夺条件:进程逐个对资源进行要求,如果一个进程获得了部分资源而得不到其他资源,就释放所拥有的资源
摒弃“环路等待”:把资源进行排序,让进程按序得到资源
常用的Hash算法有哪些
把任意长度的输入,通过hash算法,变成固定长度的输出
MD4,MD5,SHA-1
加法Hash:把输入元素一个一个的加起来构成最后的结果
位运算hash(MD5)采用的方式
乘法hash(String类里面的hashCode采用了这种方法):通过乘一个数,去尾部或者取头部
什么是一致性hash
一致性hash是如何在动态的网络拓扑中分布存储和路由,每个节点仅需维护少量相邻节点的信息,并且在节点加入/退出系统时,仅有相关的少量节点参与到拓扑的维护中,所有这一切使得一致性哈希成为第一个实用的DHT算法
Hash算法应该满足的4个适应条件
均衡性:hash的结果尽可能分布到所有的缓存中去,这样可以使得所有的缓存空间得到利用
单调性:有一些内容通过hash分派到了相应的缓存中,又有新的缓冲区到系统中,那么hash的结果应能保证原有已分配的内容可以被映射到新的缓冲区中去,而不会被映射到旧的缓冲集合中的其他缓冲区
分散性:在分布式环境中,终端有可能看不到所有的缓冲,而是看到其中一部分,当终端系统通过hash过程将内容映射到缓冲中上时,由于不同终端所见到缓冲范围有可能不同,从而导致哈希的结果不一致,最终的结果是相同的内容被不同的终端映射到不通的缓存区中
负载:问题实际上是从另一个角度看待分散性问题。既然不同的终端可能将相同的内容映射到不同的缓冲区中,那么对于一个特定的缓冲区而言,也可能被不同的用户映射为不同的内容。与分散性一样,这种情况也是应当避免的,因此好的哈希算法应能够尽量降低缓冲的负荷
Java中的NIO,BIO,AIO分别是什么
Java对BIO、NIO、AIO的支持
NIO(同步非阻塞):服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有IO请求才启动一个线程进行处理
BIO(同步并阻塞):服务器实现模式为一个连接一个线程,即客户端有连接请求到服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,可以通过线程池机制进行改善
AIO(异步非阻塞):务器实现模式为一个连接一个线程,客户端的io请求有os先完成在通知服务器应用去启动线程处理
使用场景分析
BIO方式适用于连接数目小且固定的架构,这种方式对服务器资源要求比较高、并发局限于应用中,jdk1.4以前的唯一选择,但程序直观简单理解
NIO方式适用于连接数目多且连接比较短的架构,比如聊天服务器,并发局限于应用中,编程比较复杂、jdk1.4开始支持
AIO方式使用与连接数目多且连接操作比较长的架构,比如相册服务器,充分调用了os参与并发操作,编程比较复杂,jdk7开始支持
线程同步与阻塞的关系?同步一定阻塞吗?阻塞一定同步吗
同步是指:发送方不等待接受方相应,便接着发下一个数据包的通信方式
异步:发送方发出数据后,等待到接收方的响应,才发下一个数据包的通信方式
阻塞:执行此套接字的网络调用时,直到成功才返回,否则一直阻塞在此网络调用上
非阻塞:执行套接字的网络调用时,不管是否只执行成功,就立即返回
同步不一定阻塞:
如多个人去银行办理业务(同步),但是每个人排队的时候可以打电话,聊天
阻塞不一定同步:
如一个区银行办理业务,但是银行工作人员不在(阻塞),但不能说有多个人在办理业务
如何高效的创建一个线程安全的单例
双亲委派模型中,从顶层到底层,都是哪些类加载器,分别加载了哪些类
启动(Bootstrap)类加载器:是用本地代码实现的类加载器,它负责/lib下面的类库加载到内存中(比如rt.jar)。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作
标准扩展(Extension)类加载器:是由Sun的ExtClassLoader实现的,它负责将< Java_Runtime_Home >/lib/ext或者由系统变量 java.ext.dir指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器。
系统(System)类加载器:是由 Sun 的 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的。它负责将系统类路径(CLASSPATH)中指定的类库加载到内存中。开发者可以直接使用系统类加载器
双亲委派机制描述
某个特定的类加载器在接到加载类的请求时,首先将加载任务托给父类加载器,依次递归。如果父类加载器可以完成加载任务,就返回成功;只有父类加载器无法完成此加载任务时,才自己去加载
能不能自己写个类叫:java.lang.System
通常不可以,但可以采取另类方法达到这个需求
因为在双亲委派机制中,系统会采用父类加载器,而父类加载器中有System类,所以就算自己写,也采用的是系统自带的System,但是我们可以自己定义一个类加载器来达到这个目的,未来避免双亲委托机制,这个类加载器也必须是特殊的
数据库中什么是事务?事务的隔离级别?事务的四个特性?什么是脏读、幻读、不可重复读?
什么是事务:它是一个操作序列,这些操作操作要么都执行,要不都不执行
事务的隔离级别:
Read uncommitted(读未提交):公司发了5000元到员工卡上,该员工手机提示收到工资5000元,但是boss发现发错了,就回滚将5000元改成了2000元:其中事务B(提示收款)读取了事务A还没有提交的数据(boss还没有确认的工资):出现了脏读
Read committed 读提交:该员工的老婆将钱转到另一张银行卡中,而该名员工有刚好在查询余额,显示的是2000元,拿去消费的时候发现了没有钱了:避免了脏读,导致了不可重复读。Sql Server,Oracle的默认隔离级别
Repeatable read(重复读):当员工老婆去消费了100元,查询当天消费的金额为100元,当她想打印出来的时候,刚好该名员工也付了消费金额的200元,所以打印出来的金额为300元,出现了了幻读
Serializable序列化:最高的级别,在该级别下,事务时顺序执行的,避免了脏读、不可重复读、幻读
ConcurrentHashMap怎么实现线程安全的
首先我们来了解下hashtable怎么实现线程安全的
Hashtable是针对多个读线程或者多个写线程是线程安全的,如果又有读线程又有写线程是线程不安全的。因为它里面的使用的方法加了synchronize,这这个锁是锁住了整个table,影响效率
ConcurrentHashMap是通过将hashmap分成一个一个的segment,然后将他们采用分块锁住,这样就能保证效率又能保证线程的安全,并且在读取的时候没有采用锁,其中segment是传统意义上的hashtable
concurrentHashMap在迭代的时候,是采用new出新的数据,迭代完再将头指针替换为新的数据(和mongoDB的底层的操作一样,都采用了粒度叫小的加锁)
ClassNotFoundException怎么实现的
当应用程序试图通过类的字符串名称,使用常规的三种方法装入类,但却找不到指定名称的类定义时抛出该异常
其中类加载器有:启动类加载器、标准扩展类加载器、系统类加载器
调用loadclass方法,里面执行步骤:查看是否被加载过,如果没有被加载就查看是否存在父类加载器,如果没有存在启动类加载器,通过调用本地方法native Class findBootstrapClass(String name)查找该类并加载,当双亲都没有加载都再调用系统类加载器,没有找到就抛出classNotFoundException异常
Wait和sleep的比较
调用sleep方法后,当前线程进入休眠期,暂停执行,但该线程继续拥有监视资源的所有权,到达休眠时间后线程将继续执行,直达完成,若在休眠期另一个线程中断该线程,则该线程退出
调用wait方法后,该线程放弃监视资源的所有权进入等待状态,等待有其他线程调用notify()或者notifyAll()进入调用状态,与其他线程共同争夺监视
AOP是什么,实现方式是什么
面向切面编程,如:添加日志,当一个方法调用后,制动执行添加日志功能
实现方式
Jdk代理(需要被代理对象实现一个接口)
Cglib代理实现aop,不需要被代理对对象实现一个接口,被代理对象不能是final对象,且被代理对象不能是单例
Jdk动态代理的实现
InvocationHandleer的invoke方法是谁调用的
实际上调用invoke方法,是调用MyInvocationHandler里面的Invoke方法
代理对象是怎么生成的http://rejoy.iteye.com/blog/1627405
通过getProxyClass方法得到代理类,调用代理类的构造方法,并将被代理对象的实例传递给它的构造方法(这里采用的是单例模式:getInstance)
getProxyClass类的具体实现,需要注意的要点
被代理对象的接口不能超过65535个:能写出这样的类的人一定能NB
遍历被代理对象接口,从而放在一个set集合中,然后把实现接口的放在map集合的缓存中,其中从缓存中取对象是线程安全的
调用proxyGenerator类中的generateProxyClass的方法:这里是生成代理类的class字节码的地方
generateProxyClass方法的实现这里就不讲了,主要是生成了字节码对象那个,然后保存在硬盘上调用的是ProxyGeneratorUtils里面的wirteProxyClassToHardDisk方法
Cglib动态代理的实现
CGlib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑,jdk动态代理与CGlib动态代理都是实现Spring AOP的基础
Jdk自带的动态代理与CGLib动态代理的比较
CGLib创建动态代理对象性能比jdk创建的动态代理对象的性能高步少,但是CGLib在创建对象时所花费的时间却比jdk多的多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用jdk方式要更为合适些。同时,由于CGLIb由于采用动态创建子类的方式,对于final方法,无法进行代理
实现线程安全的方式
使用synchronized;
包括对类进行修饰
和对方法进行修饰
Object方法里面的wait、notify
可以解决资源竞争的问题
ThreadLocal机制
方法锁和静态方法锁的区别
方法锁能保证每个对象之间是互斥的,也就是线程安全的
静态锁和实例方法上的锁,默认不同的,如果同步需要制定两把锁
同一个类中的方法上的锁,来自于调用该方法的对象,如果调用该方法的对象是相同的,那么锁必然相同,,否则就不同,如果对象是单例的话,就能互斥
静态方法加锁,能和所有其他静态方法加锁互斥
怎么实现自己的类加载器
首先需要继承ClassLoader类,然后写一个方法
写一个方法,将字节流将加载.class文件,并返回字节数组
重写findClass方法,判断是否存在该class文件
在用该类加载器的loadClass方法记载该类
Java8新特性
http://blog.youkuaiyun.com/lifuxiangcaohui/article/details/41925415
允许接口添加一个非抽象的方法实现,只需要使用default关键字
使用了Lambda表达式
函数式接口
方法与构造函数引用
访问局部变量
访问对象字段与静态变量
访问接口的默认方法
Date API
Annotation注解
互联网的发展
首先了解下电脑的历史:1946年,第一台电子计算机在美国问世,到现在短短的70年的发展,计算机已经是一个门非常庞大的学问,它发展的速度超过了任何的学科发展的速度
现在技术大部分都建立在军事的发展上,计算机也不例外,但是一门技术需要蓬勃发展需要的是市场化运行,其中1965年,世界上第一台真正意义上的小型机pdp-8问世,从而迎来了计算机发展的高峰期
1969年出现了通信处理机IMP,标识着计算机可以进入了互联网时代
从体来说,互联网的发展经历了:国家–大型企业–公司–个人的发展,这也在一面反射出互联网未来的发展情况的良好性
互联网前几年主要再与发展交互(亲戚朋友时间的交互、商人与卖家交互、国家部门之间的交互)
JAVA实现远程调用有哪些方式
RMI > Httpinvoker >= Hessian >> Burlap >> web service
详细信息介绍
Jdk中采用的设计模式
抽象工厂:ArrayList.asList
代理模式:reflect.Proxy
单例模式:Runtime.getRuntime()
工厂方法:Proxy.newProxyInstance()
建造者:stringBuilder.append();
原型:Object.clone();
组合模式:List.addAll(Collection c);
享元:Integer.valueOf(int i);
装饰器:BufferedInputStream(InputStream is);
门面:lang.class
Java的锁机制说明
每个对象都有一个锁、并且是唯一的
在静态方法上枷锁和普通方法上加锁、用的不是同一把锁、不是同一把钥匙
对象锁:java为每个创建出来的对象都使用同个对象锁
类锁:一个类拥有一个锁
打开淘宝网页直到显示完毕,中途发生了什么
打开网址(http://www.taobao.com),通过网址可以得到请求协议为http
通过网址(www.taobao.com)解析到相应的服务器IP,通www.taobao.com可以解析到主机的ip地址,然后将请求参数进行封装到http协议里面,服务器创建request域中接收
其中使用http协议与服务器建立连接需要(三次握手),才能建立成功
然后服务器对请求进行解析。一般主页面在服务器缓存中存在,所以可以直接通过http协议将信息封装到request域发送到浏览器
浏览器对http进行解析,浏览器只能解析静态代码,动态代码一般是直接显示
Spring的IOC的实现原理
http://www.cnblogs.com/ITtangtang/p/3978349.html
SSH的实现代码多看看
如何在高并发中防止死锁
http://blog.youkuaiyun.com/runyon1982/article/details/49018581
数据库代码
更新代码:update 表名 set 字段名 where
查询代码:select 字段名 from 表名 where
删除代码:delete 表名 where
添加代码:insert into 表名(字段名) value
Linux系统的基本命令
字节流与字符流之间的桥梁
OutputStreamWriter或者InputStreamReader
数据库怎么设置一个全局变量
Set @字段名=’属性值
数据库怎么开启一个事务
Begin;rollback;commit;
怎么在一个文件盘中找到特定的a.txt文件
通过set集合保存已经遍历的文件路径
如果存在则跳过遍历
如果不存在则遍历当前文件夹
DOM与SAX解析xml文件的特定
http://note.youdao.com/yws/public/redirect/share?id=85c0f9da2ec4df42323709fd827b71af&type=true
Hibernate的id生成策略
http://note.youdao.com/yws/public/redirect/share?id=16c1fd1404428a3d8a47a65b27b8e6ce&type=false
Ssh框架的基本介绍
Spring的事务管理
http://note.youdao.com/yws/public/redirect/share?id=8bf68f845230f0a46b934c4cec385b8c&type=false
Struts1的执行流程
1、读取配置文件(初始化ModelConfig对象),Struts框架总控制器(ActionServelt)是一个Servlet,在web.xml中配置成自动启动的servelt读取配置文件(Struts-config.xml)的配置信息,为不同的Struts模块初始化相应的ModeleConfig对象:ActionConfig、ControlConfig、FormBeanConfig、ForwardConfig、MessageResourcesConfig
2、 用户提交表单或调用URL向web应用程序器提交一个请求,请求的数据用Http协议上传给web服务器
3、 填充Form(实例化、复位、填充数据、校验、保存)
(.do请求)从ActionConfig中找出对应该请求的Action子类。如没有对应的action,控制器直接转发给JSP或静态页面。如有对应的Action且这个Action有一个对应的Action Form,ActionForm被实例化并且用HTTP请求的数据填充其属性,并且保存在Servlet Context中,这样它们就可以被其它Action对象或者JSP使用
4、派发请求
控制器根据配置信息ActionConfig将请求派发到具体的Action,相应的FormBean一并传给这个Action的execute()方法
5、处理业务
Action一般只包含一个execute方法,它负责执行相应的业务逻辑。完毕返回一个ActionForward对象,控制器通过该ActionForward对象进行转发工作
6、Action根据业务处理的不同结果返回一个目标响应对象给总控制器,该目标响应对象对应一个具体的JSP页面或另一个Action
7、查找响应
总控制器根据业务功能Action返回的目标响应对象,找到对应的资源对象,通常是一个具体的JSP页面
8、响应用户
目标响应对象将结果展现给用户目标响应对象,将结果页面展现给用户
Struts1的action初始化问题
Action的初始化时在第一个请求到来时,初始化并且只初始化一次:不同页面调用action的不同方法也是只初始化一次;所以action是线程不安全的,因为所有的请求共享一个实例
怎么实现action的安全性编程
1、注意不要使用实例变量或者类变量共享只是针对某个请求的数据
2、注意资源操作的同步性
Struts1的填充form表单的步骤
1、页面调用XXX.do请求
2、查看action是否有name属性(根据name与scope查询:Scope.getAttribute(name))
3、是否找到:3.1、没有则创建一个新的FormBean对象(Scope.setAttribute(name,form));3.2有则返回这个FormBean
4、调用reset方法
5、通过request域得到相应的属性值
6、查看是否有校验功能:有则对属性值进行校验,通过则继续执行,不同过则跳转到错误页面(通过自己设置跳转目标),没有则跳到6
7、调用相应属性值的setter,往formBean填充数据
Struts1的属性值填充
1、是根据真正的set方法来进行填充:如果在form表单中的username,但是在User对象中有name,但是这个对象中有setUsername(String username){this.name = username;}也可以进行对User对象的数据进行填充
网络编程方面的知识
1、什么叫做防火墙
位于Internet和本地网络之间检查所有进出的数据以保证其合法性的硬件和软件
为什么DataOutputStream中的readLIne()不推荐使用
应该它在大多数情况下不能正确地将非ASCII字符转化为字节,推荐使用BufferReader类的readLine()方法处理,但是这两个方法都有同一个隐含的BUG,它们不一定会把一个回车看作行的结束,相反,readLine()只识别换行或回车/换行对。当在流中检测到回车是,readLIne()会再继续之前等待,查看下一个字符是否为换行,如果是换行,就抛掉回车和换行,把这一行作为String返回,如果不是换行,就抛掉回车,把这一行作为String返回,这个额外的字符会作为下一行的一部分读取,但是,如果回车是流的最后一个字符,那么readLIne()就会被挂起,等待最后一个字符的出现,这个字符永远也不会出现