1:linux线程和进程的区别?javascript
进程是程序执行时的一个实例,即它是程序已经执行到课中程度的数据结构的聚集。从内核的观点看,进程的目的就是担当分配系统资源(CPU时间、内存等)的基本单位。html
线程是进程的一个执行流,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。一个进程由几个线程组成(拥有不少相对独立的执行流的用户程序共享应用程序的大部分数据结构),线程与同属一个进程的其余的线程共享进程所拥有的所有资源。java
进程是资源分配的最小单位,线程是CPU调度的最小单位node
使用多线程的理由之一是和进程相比,它是一种很是"节俭"的多任务操做方式。咱们知道,在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,创建众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工做方式。而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,并且,线程间彼此切换所需的时间也远远小于进程间切换所须要的时间。据统计,总的说来,一个进程的开销大约是一个线程开销的30倍左右,固然,在具体的系统上,这个数据可能会有较大的区别。mysql
使用多线程的理由之二是线程间方便的通讯机制。对不一样进程来讲,它们具备独立的数据空间,要进行数据的传递只能经过通讯的方式进行,这种方式不只费时,并且很不方便。线程则否则,因为同一进程下的线程之间共享数据空间,因此一个线程的数据能够直接为其它线程所用,这不只快捷,并且方便。固然,数据的共享也带来其余一些问题,有的变量不能同时被两个线程所修改,有的子程序中声明为static的数据更有可能给多线程程序带来灾难性的打击,这些正是编写多线程程序时最须要注意的地方linux
2:一致性hash算法正则表达式
问题引入:为何须要一致性hash?算法
在分布式系统中,若是某业务能够由多个相同的节点处理,很容易想到用HASH的方式将业务请求分散到这些节点处理,若是有N个节点,计算方法为:HASH(id)% N。spring
若是只是简单的计算,不涉及用户状态,这是一个简单有效的方案。若是节点的计算涉及用户状态,好比维护购物车、Memcache缓存服务等,好像也没什么问题,只要用同一个数据作id,上述HASH的结果也保持不变。但若是节点数量发生变化,好比因为业务量的增大而增长节点或因为机器宕机而减小节点,上述HASH的结果就不同了。若增长2个节点,某id原处理节点为HASH(id)% N,新的处理节点就变成了HASH(id)% (N + 2),可能会将大量id的处理节点打乱从新分配,就会发现以前某节点保存的用户数据用不到了,而新的处理节点根本没有这些数据。在这段时间内,这些用户的状态受到破坏,若是是购物车,车里的东西都没了,若是是缓存服务,以前的缓存都消失了,起不到缓存的效果。可能须要用户从新登陆,可能须要从数据库更新缓存,可能由此引入新的问题。sql
一致性哈希在必定程度上缓解了这个问题 步骤为:
1.将整个哈希值空间组织成一个虚拟圆环,假设某哈希函数H的值空间为0-(2^32-1),即32位无符号整数
2.将各节点用H函数哈希,能够将服务器的IP或主机名做为关键字哈希,这样每一个节点就能肯定其在哈希环上的位置
3.将id用H函数映射到哈希空间的一个值,沿该值向后,将遇到的第一个节点作为处理节点
下图中,若某id的HASH值落在node1和node2各自HASH值的中间位置,则此id对应的业务请求由node2处理。
当增长服务节点时,只会影响与之相邻的某一节点,其余节点不受影响。若是在node2和node4之间增长一个node5,则只有node4处理的部分 id(HASH值落在node2以后、node5以前的那部分id)变为由node5来处理,其余节点处理的id不变。比开头所述的简单HASH方式有了 很大的改善。
若是节点数很少,将这些节点映射到值空间以后,分布可能会很不均匀,必然会形成个别节点处理的id数量远大于其余节点,这就起不到负载均衡的效果。这能够 经过引入虚拟节点的方式解决,即对每个节点计算多个HASH值,尽可能保证这些HASH值比较均匀的分布在值空间中。当根据id查找节点时,找到的是虚拟 节点,而后再根据虚拟节点查找对应的真实节点。多了一次查找的过程。
3:TCP和UDP的区别?
TCP协议的三次握手 四次挥手
位码即tcp标志位,有6种标示:SYN(synchronous创建联机)、 ACK(acknowledgement 确认) 、PSH(push传送) FIN(finish结束)、 RST(reset重置) 、 URG(urgent紧急) 、Sequence number(顺序号码)、 Acknowledge number(确认号码)
第一次握手:主机A发送位码为syn=1,随机产生seq number=1234567的数据包到服务器,主机B由SYN=1知道,A要求创建联机;
第二次握手:主机B收到请求后要确认联机信息,向A发送ack number=(主机A的seq+1),syn=1,ack=1,随机产生seq=7654321的包
第三次握手:主机A收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,主机A会再发送ack number=(主机B的seq+1),ack=1,主机B收到后确认seq值与ack=1则链接创建成功。
完成三次握手,主机A与主机B开始传送数据
1) 基于链接与无链接;
2) 对系统资源的要求(TCP较多,UDP少);
3) UDP程序结构较简单;
4) 流模式与数据报模式 ;
5) TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。
说明状况下使用TCP和UDP呢?
在注重速度的时候使用UDP---》如:视频聊天时,语音聊天
在注重安全的时候使用TCP---》如:下载文件时
4:linux进程通讯
进程通讯有以下一些目的:
A、数据传输:一个进程须要将它的数据发送给另外一个进程,发送的数据量在一个字节到几M字节之间
B、共享数据:多个进程想要操做共享数据,一个进程对共享数据的修改,别的进程应该马上看到。
C、通知事件:一个进程须要向另外一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
D、资源共享:多个进程之间共享一样的资源。为了做到这一点,须要内核提供锁和同步机制。
E、进程控制:有些进程但愿彻底控制另外一个进程的执行(如Debug进程),此时控制进程但愿可以拦截另外一个进程的全部陷入和异常,并可以及时知道它的状态改变。
如今linux使用的进程间通讯方式:
(1)管道(pipe)和有名管道(FIFO)
(2)信号(signal)
(3)消息队列
(4)共享内存
(5)信号量
(6)套接字(socket)
5:如何实现手机通信录的查找时候的提示功能?
功能:输入拼音、电话号码、中文姓名、姓名首字母缩写查询
6:B+树?
B+树是根据多路查找树 ---> B树的延伸 出来的树的数据结构,是为了方便遍历而来的,由于全部的关键字都在叶子节点上,且是有一个链表来维持顺序的。
7:mysql引擎
存储引擎是什么?
MySQL中的数据用各类不一样的技术存储在文件(或者内存)中。这些技术中的每一种技术都使用不一样的存储机制、索引技巧、锁定水平而且最终提供普遍的不一样的功能和能力。
经过选择不一样的技术,你可以得到额外的速度或者功能,从而改善你的应用的总体功能。
例如,若是你在研究大量的临时数据,你也许须要使用内存存储引擎。内存存储引擎可以在内存中存储全部的表格数据。又或者,你也许须要一个支持事务处理的数据库(以确保事务处理不成功时数据的回退能力)。
这些不一样的技术以及配套的相关功能在MySQL中被称做存储引擎(也称做表类型)。MySQL默认配置了许多不一样的存储引擎,能够预先设置或者在 MySQL服务器中启用。你能够选择适用于服务器、数据库和表格的存储引擎,以便在选择如何存储你的信息、如何检索这些信息以及你须要你的数据结合什么性 能和功能的时候为你提供最大的灵活性
8:TCP/IP知识,IP四元组
9:快排和堆排序的原理
10:java虚拟机
(1) jvm启动流程
(2) jvm基本结构
(3) 内存模型
(4) 解释运行和编译运行
11:java类加载机制
类从被加载到虚拟机内存中开始,直到卸载出内存为止,它的整个生命周期包括了: 加载、验证、准备、解析、初始化、使用和卸载 这7个阶段。其中, 验证、准备和解析这三个部分统称为链接(linking)
12:ARP(地址解析协议),请用简单语言说明其的工做原理
1. 首先,每台主机都会在本身的ARP缓冲区 (ARP Cache)中创建一个 ARP列表,以表示IP地址和MAC地址的对应关系。
2. 当源主机须要将一个数据包要发送到目的主机时,会首先检查本身 ARP列表中是否存在该 IP地址对应的MAC地址,
若是有﹐就直接将数据包发送到这个MAC地址;若是没有,就向本地网段发起一个ARP请求的广播包,查询此目的主机对应的MAC地址。此ARP请求数据包里包括源主机的IP地址、硬件地址、以及目的主机的IP地址。
3. 网络中全部的主机收到这个ARP请求后,会检查数据包中的目的IP是否和本身的IP地址一致。若是不相同就忽略此数据包;若是相同,该主机首先将发送端的MAC地址和IP地址添加到本身的ARP列表中,若是ARP表中已经存在该IP的信息,则将其覆盖,而后给源主机发送一个 ARP响应数据包,告诉对方本身是它须要查找的MAC地址;
4. 源主机收到这个ARP响应数据包后,将获得的目的主机的IP地址和MAC地址添加到本身的ARP列表中,并利用此信息开始数据的传输。若是源主机一直没有收到ARP响应数据包,表示ARP查询失败。
13:OSI七层模型
应用层: 文件传输,电子邮件,文件服务,虚拟终端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet
表示层: 数据格式化,代码转换,数据加密 没有协议. (信息的语法语义以及它们的关联、如加密解密、转换翻译、压缩解压缩)
会话层: 解除或创建与别的接点的联系 没有协议 (不一样机器上的用户之间创建及管理会话)
传输层: 提供端对端的接口 TCP,UDP (接受上一层的数据,在必要的时候把数据进行分割,并将这些数据交给网络层,且保证这些数据段有效到达对端)
网络层: 为数据包选择路由 IP,ICMP,RIP,OSPF,BGP,IGMP (控制子网的运行,如逻辑编址、分组传输、路由选择)
数据链路层: 传输有地址的帧以及错误检测功能 SLIP,CSLIP,PPP,ARP,RARP,MTU (物理寻址,同时将原始比特流转变为逻辑传输线路)
物理层: 以二进制数据形式在物理媒体上传输数据 ISO2110,IEEE802,IEEE802.2 (机械、电子定时接口通讯信道上的原始比特流传输 )
14:HTTP协议的使用过程
(1) 请求:客户端向服务器索要数据
http协议规定:一个完整的http请求包含'请求行','请求头','请求体'三个部分;
请求行:包含了请求方法,请求资源路径,http协议版本. "GET /resources/images/ HTTP/1.1"
请求头:包含了对客户端的环境描述,客户端请求的主机地址等信息.
Accept: text/html ( 客户端所能接收的数据类型 )
Accept-Language: zh-cn ( 客户端的语言环境 )
Accept-Encoding: gzip( 客户端支持的数据压缩格式 )
Host: m.baidu.com( 客户端想访问的服务器主机地址 )
User-Agent: Mozilla/5.0(Macintosh;Intel Mac OS X10.10 rv:37.0) Gecko/20100101Firefox/37.0( 客户端的类型,客户端的软件环境 )
请求体:客户端发给服务器的具体数据,好比文件/图片等.
(2) 响应:服务器返回客户端想要的数据
http协议规定:一个完整的http响应包含'状态行','响应头','实体内容'三个部分;
状态行:包含了http协议版本,状态吗,状态英文名称."HTTP/1.1 200 OK"
响应头:包含了对服务器的描述,对返回数据的描述.
Content-Encoding: gzip(服务器支持的数据压缩格式) Content-Length: 1528(返回数据的长度)
Content-Type:application/xhtml+xml;charset=utf-8(返回数据的类型)
Date: Mon,15Jun201509:06:46GMT(响应的时间) Server: apache (服务器类型)
实体内容:服务器返回给客户端的具体数据(图片/html/文件...).
15:SQL注入
SQL Injection:就是经过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
具体来讲,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它能够经过在Web表单中输入(恶意)SQL语句获得一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。
如何防止SQL Injection:
1.永远不要信任用户的输入,要对用户的输入进行校验,能够经过正则表达式,或限制长度,对单引号和双"-"进行转换等。
2.永远不要使用动态拼装SQL,可使用参数化的SQL或者直接使用存储过程进行数据查询存取。
3.永远不要使用管理员权限的数据库链接,为每一个应用使用单独的权限有限的数据库链接。
4.不要把机密信息明文存放,请加密或者hash掉密码和敏感的信息。
5.应用的异常信息应该给出尽量少的提示,最好使用自定义的错误信息对原始错误信息进行包装,把异常信息存放在独立的表中。
16:spring的工做原理
spring的最大做用ioc/di,将类与类的依赖关系写在配置文件中,程序在运行时根据配置文件动态加载依赖的类,下降的类与类之间的藕合度。它的原理是在applicationContext.xml加入bean标签,在bean标签中经过class属性说明具体类名、经过property标签说明该类的属性名、经过constructor-args说明构造子的参数。其一切都是反射,当经过applicationContext.getBean("id名称")获得一个类实例时,就是以bean标签的类名、属性名、构造子的参数为准,经过反射实例对象,唤起对象的set方法设置属性值、经过构造子的newInstance实例化获得对象。正由于spring一切都是反射,反射比直接调用的处理速度慢,因此这也是spring的一个问题。
spring第二大做用就是aop,其机理来自于代理模式,代理模式有三个角色分别是通用接口、代理、真实对象代理、真实对象实现的是同一接口,将真实对象做为代理的一个属性,向客户端公开的是代理,当客户端调用代理的方法时,代理找到真实对象,调用真实对象方法,在调用以前以后提供相关的服务,如事务、安全、日志。其名称分别是代理、真实对象、装备、关切点、链接点。
Spring目的:就是让对象与对象(模块与模块)之间的关系没有经过代码来关联,都是经过配置类说明 管理的(Spring根据这些配置 内部经过反射去动态的组装对象)
17:Hibernate中java对象的三种状态的区别
实体对象的生命周期在Hibernate应用中是一个很关键的概念,正确的理解实体对象的生命周期将对咱们应用Hibernate作持久层设计起到很大的做 用.而所谓的实体对象的生命周期就是指实体对象由产生到被GC回收的一段过程.在这过程当中咱们须要理解的就是实体对象生命周期中的三种状态.
瞬时状态(临时状态) transient:刚刚用new建立,尚未被持久化,不处于Session的缓存中,处于临时状态的Java对象被称为临时对象(无数据、无Session)
持久化状态 persistent:已经被持久化,加入到Session的缓存中。处于持久化状态的Java对象被称为持久化对象(有数据,有Session)
游离状态 detached:已经被持久化,但再也不处于Session的缓存中。处于游离状态的Java对象被称为游离对象(有数据,无Session)
详细解析:新new出来的对象如Student stu = new Student(),就是瞬时对象,它在内存中孤立存在,它的意义是携带信息的载体,不和数据库的数据有任何关联。经过Session的save()或saveOrUpdate()方法能够把一个瞬时对象与数据库相关联,并把瞬时对象携带的信息经过配置文件所作的映射插入到数据库中,这个瞬时对象就转化成了持久对象(使用get(),load()等方法查询到的数据对象,一出场就是持久对象),并拥有和数据库记录相同的id标识(Hibernate自动将id值赋予它)。若是这时候使用delete()方法,它就会变回瞬时对象,删除了数据库与这个对象关联的记录,对象与数据库再也不有任何的关联。当一个Session指定close()或clear(),evict()以后,持久对象就变成脱管对象,这时对象的id虽然拥有数据库识别值,但他们目前并不在Hibernate持久层的管理下,它与瞬时对象的本质是相同的,只不过比瞬时对象多了数据标识的id值。脱管对象的引用依然有效,对象能够继续被修改,当它从新被关联到某个新的Session上时,会再次变成持久对象(脱管状态期间的改动将被持久化到数据库上)。脱管对象拥有数据库识别值id,因此它能够经过update(),saveOrUpdate(),lock()等方法,再度与持久层关联。
18:Hibernate的缓存机制
Hibernate缓存的做用:
Hibernate是一个持久层框架,常常访问物理数据库,为了下降应用程序对物理数据源访问的频次,从而提升应用程序的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据
Hibernate缓存分类:
Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存
Hibernate一级缓存又称为“Session的缓存”,它是内置的,意思就是说,只要你使用hibernate就必须使用session缓存。因为Session对象的生命周期一般对应一个数据库事务或者一个应用事务,所以它的缓存是事务范围的缓存。在第一级缓存中,持久化类的每一个实例都具备惟一的OID。
Hibernate二级缓存又称为“SessionFactory的缓存”,因为SessionFactory对象的生命周期和应用程序的整个过程对应,所以Hibernate二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,所以须要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。第二级缓存是可选的,是一个可配置的插件,在默认状况下,SessionFactory不会启用这个插件。
什么样的数据适合存放到第二级缓存中?
1 不多被修改的数据
2 不是很重要的数据,容许出现偶尔并发的数据
3 不会被并发访问的数据
4 常量数据
Hibernate查找对象如何应用缓存?
当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,若是配置了二级缓存,那么从二级缓存中查;若是都查不到,再查询数据库,把结果按照ID放入到缓存
删除、更新、增长数据的时候,同时更新缓存
19:Hibernate是如何延迟加载
延迟加载机制是为了不一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正须要数据的时候,才真正执行数据加载操做。Hibernate中主要是经过代理(proxy)机制来实现延迟加载。它的具体过程:Hibernate丛数据库获取某一个对象数据时、获取某一个对象的集合属性值时,或获取某一个对象所关联的另外一个对象时,因为没有使用该对象的数据,hibernate并非数据库加载真正的数据,而只是为该对 象建立一个代理对象来表明这个对象,这个对象上的全部属性都是默认值;只有在真正须要使用该对象的数据时才建立这个真实对象,真正从数据库中加载它的数 据,这样在某些状况下,就能够提升查询效率。
集合属性的延迟加载
当 Hibernate 从数据库中初始化某个持久化实体时,该实体的集合属性是否随持久化类一块儿初始化呢?若是集合属性里包含十万,甚至百万的记录,在初始化持久化实体的同时,完成全部集合属性的抓取,将致使性能急剧降低。彻底有可能系统只须要使用持久化类集合属性中的部分记录,而彻底不是集合属性的所有,这样,没有必要一次加载全部的集合属性。
对于集合属性,一般推荐使用延迟加载策略。所谓延迟加载就是等系统须要使用集合属性时才从数据库装载关联的数据
20:分页查询
分页查询分为两类:逻辑分页,物理分页,咱们先从理论上理解一下:
逻辑分页概述:就是用户第一次访问时,将数据库的全部记录所有查询出来,添加到一个大的集合中,而后存放在session对象,而后经过页码计算出当前页须要显示的数据内容,存储到一个小的list的集合中,并将之存储到request对象中,跳转到JSP页面,进行遍历显示。 当用户第二次访问时,只要不关闭浏览器,咱们还会从session中获取数据,来进行显示。为何叫逻辑分页呢?由于此种方法是在内存的session对象中进行计算分页显示的,而不是真正的将咱们数据库进行分页的。
缺点:
a,若是须要查询的数据量过大,session将耗费大量的内存;
b,由于是在session中获取数据,若是第二次或者更多此的不关闭浏览器访问,会直接访问session,从而不能保证数据是最新的。
小结:这种分页不多使用。可是在数据量小,不会被修改的数据,使用逻辑分页会提升程序的执行效率。
物理分页概述:使用数据库自身所带的分页机制,例如,Oracle数据库的rownum,或者Mysql数据库中的limit等机制来完成分页操做。由于是对数据库实实在在的数据进行分页条件查询,因此叫物理分页。每一次物理分页都会去链接数据库。
优势:数据可以保证最新,因为根据分页条件会查询出少许的数据,因此不会占用太多的内存。
缺点:物理分页使用了数据库自身带的机制,因此这样的SQL语句不通用,致使不能进行数据库的移植。
小结:在实际中物理分页仍是使用的较多的。
21:forward和redirect
redirect:请求重定向:客户端行为,本质上为2次请求,地址栏改变,前一次请求对象消失,是服务器向用户发送转向的地址,redirect后地址栏变成新的地址。
forward:请求转发:服务器行为,服务器获取跳转页面内容传给用户,用户地址栏不变
重定向和转发有一个重要的不一样:当使用转发时,JSP容器将使用一个内部的方法来调用目标页面,新的页面继续处理同一个请求,而浏览器将不会知道这个过程。 与之相反,重定向方式的含义是第一个页面通知浏览器发送一个新的页面请求。由于,当你使用重定向时,浏览器中所显示的URL会变成新页面的URL, 而当使用转发时,该URL会保持不变。重定向的速度比转发慢,由于浏览器还得发出一个新的请求。同时,因为重定向方式产生了一个新的请求,因此通过一次重定向后,request内的对象将没法使用。
怎么选择是重定向仍是转发呢?一般状况下转发更快,并且能保持request内的对象,因此他是第一选择。可是因为在转发以后,浏览器中URL仍然指向开始页面,此时若是重载当前页面,开始页面将会被从新调用。若是你不想看到这样的状况,则选择转发
22:HashMap底层数据结构和原理
底层数据结构:
HashMap其实是一个“链表的数组”的数据结构,每一个元素存放链表头结点的数组,即数组和链表的结合体。
当咱们往HashMap中put元素的时候,先根据key的hashCode从新计算hash值,根据hash值获得这个元素在数组中的位置(即下标),若是数组该位置上已经存放有其余元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最早加入的放在链尾。若是数组该位置上没有元素,就直接将该元素放到此数组中的该位置上
从HashMap中get元素时,首先计算key的hashCode,找到数组中对应位置的某一元素,而后经过key的equals方法在对应位置的链表中找到须要的元素。
总结:HashMap 在底层将 key-value 当成一个总体进行处理,这个总体就是一个 Entry 对象。HashMap 底层采用一个 Entry[] 数组来保存全部的 key-value 对,当须要存储一个 Entry 对象时,会根据hash算法来决定其在数组中的存储位置,在根据equals方法决定其在该数组位置上的链表中的存储位置;当须要取出一个Entry时,也会根据hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Entry。
HashMap(线程不安全)与HashTable(线程安全)的区别
(1)二者最主要的区别在于Hashtable是线程安全,而HashMap则非线程安全
Hashtable的实现方法里面都添加了synchronized关键字来确保线程同步,所以相对而言HashMap性能会高一些,咱们平时使用时若无特殊需求建议使用HashMap,在多线程环境下若使用HashMap须要使用Collections.synchronizedMap()方法来获取一个线程安全的集合(Collections.synchronizedMap()实现原理是Collections定义了一个SynchronizedMap的内部类,这个类实现了Map接口,在调用方法时使用synchronized来保证线程同步,固然了实际上操做的仍是咱们传入的HashMap实例,简单的说就是Collections.synchronizedMap()方法帮咱们在操做HashMap时自动添加了synchronized来实现线程同步,相似的其它Collections.synchronizedXX方法也是相似原理)
(2) HashMap和Hashtable的底层实现都是数组+链表结构实现
(3) HashMap可使用null做为key,而Hashtable则不容许null做为key
虽然说HashMap支持null值做为key,不过建议仍是尽可能避免这样使用,由于一旦不当心使用了,若所以引起一些问题,排查起来非常费事
HashMap以null做为key时,老是存储在table数组的第一个节点上
(4) HashMap是对Map接口的实现,HashTable实现了Map接口和Dictionary抽象类
22: String、StringBuffer(线程安全)、StringBuilder(线程不安全)区别
StringBuffer、StringBuilder和String同样,也用来表明字符串。String类是不可变类,任何对String的改变都 会引起新的String对象的生成;StringBuffer则是可变类,任何对它所指代的字符串的改变都不会产生新的对象。既然可变和不可变都有了,为什么还有一个StringBuilder呢?相信初期的你,在进行append时,通常都会选择StringBuffer吧!
先说一下集合的故事,HashTable是线程安全的,不少方法都是synchronized方法,而HashMap不是线程安全的,但其在单线程程序中的性能比HashTable要高。StringBuffer和StringBuilder类的区别也是如此,他们的原理和操做基本相同,区别在于StringBuffer支持并发操做,线性安全的,适合多线程中使用。StringBuilder不支持并发操做,线性不安全的,不适合多线程中使用。新引入的StringBuilder类不是线程安全的,但其在单线程中的性能比StringBuffer高。
23:java中的四种引用类型
⑷ 强引用(StrongReference)、⑵软引用(SoftReference)、⑶弱引用(WeakReference)、
⑷虚引用(PhantomReference)
24:java的基础类型和字节
java四类八种基本数据类型
第一类:整型 byte short int long
第二类:浮点型 float double
第三类:逻辑型 boolean(它只有两个值可取true false)
第四类:字符型 char
引用数据类型:是数据的引用在栈中,可是他的对象在堆中。在栈中能够直接分配内存的数据是基本数据类型。
字节:
boolean 布尔型 1/8
byte 字节类型 1
char 字符型 2 一个字符能存储一个中文汉字
short 短整型 2
int 整数类型 4
float 浮点类型(单精度) 4
long 长整形 8
double 双精度类型(双精度) 8
25:调用start()方法和run()的区别
区别:调用start方法实现多线程,而调用run方法没有实现多线程
Start:
用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。经过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并无运行,一旦获得spu时间片,就开始执行run()方法,这里方法run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。
Run:
run()方法只是类的一个普通方法而已,若是直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径仍是只有一条,仍是要顺序执行,仍是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。
总结:调用start方法方可启动线程,而run方法只是thread的一个普通方法调用,仍是在主线程里执行。
26:实现多线程有几种方式,多线程同步怎么作
实现线程有2种方式:继承Thread类或者实现Runnable接口
实现同步也有两种方式,一种是用同步方法,另外一种是用同步块
27:http中,get post的区别
Http定义了与服务器交互的不一样方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE。URL全称是资源描述符,咱们能够这样认为:一个URL地址,它用于描述一个网络上的资源,而HTTP中的GET,POST,PUT,DELETE就对应着对这个资源的查,改,增,删4个操做。到这里,你们应该有个大概的了解了,GET通常用于获取/查询资源信息,而POST通常用于更新资源信息
1.根据HTTP规范,GET用于信息获取,并且应该是安全的和幂等的。
2.根据HTTP规范,POST表示可能修改变服务器上的资源的请求
不少人却没有按照HTTP规范去作,致使这个问题的缘由有不少,好比说:
1.不少人贪方便,更新资源时用了GET,由于用POST必需要到FORM(表单),这样会麻烦一点。
2.对资源的增,删,改,查操做,其实均可以经过GET/POST完成,不须要用到PUT和DELETE。
3.另一个是,早期的Web MVC框架设计者们并无有意识地将URL看成抽象的资源来看待和设计,因此致使一个比较严重的问题是传统的Web MVC框架基本上都只支持GET和POST两种HTTP方法,而不支持PUT和DELETE方法
表面现象上面看看GET和POST的区别:
1.GET请求的数据会附在URL以后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,参数之间以&相连,如:login.action?name=hyddd&password=idontknow&verify=%E4%BD%A0%E5%A5%BD。若是数据是英文字母/数字,原样发送,若是是空格,转换为+,若是是中文/其余字符,则直接把字符串用BASE64加密,得出如:%E4%BD%A0%E5%A5%BD,其中%XX中的XX为该符号以16进制表示的ASCII。
POST把提交的数据则放置在是HTTP包的包体中。
2."GET方式提交的数据最多只能是1024字节,理论上POST没有限制,可传较大量的数据
实际解释:
(1).首先是"GET方式提交的数据最多只能是1024字节",由于GET是经过URL提交数据,那么GET可提交的数据量就跟URL的长度有直接关系了。而实际上,URL不存在参数上限的问题,HTTP协议规范没有对URL长度进行限制。这个限制是特定的浏览器及服务器对它的限制。IE对URL长度的限制是2083字节(2K+35)。对于其余浏览器,如Netscape、FireFox等,理论上没有长度限制,其限制取决于操做系统的支持。
注意这是限制是整个URL长度,而不只仅是你的参数值数据长度。
(2).理论上讲,POST是没有大小限制的,HTTP协议规范也没有进行大小限制,说“POST数据量存在80K/100K的大小限制”是不许确的,POST数据是没有限制的,起限制做用的是服务器的处理程序的处理能力。
里外一种答案方式:
GET方法:
使用GET方法时,查询字符串(键值对)被附加在URL地址后面一块儿发送到服务器:
/test/demo_form.jsp?name1=value1&name2=value2
特色:
GET请求可以被缓存
GET请求会保存在浏览器的浏览记录中
以GET请求的URL可以保存为浏览器书签
GET请求有长度限制
GET请求主要用以获取数据
POST方法:
使用POST方法时,查询字符串在POST信息中单独存在,和HTTP请求一块儿发送到服务器:
POST /test/demo_form.jsp HTTP/1.1
Host: w3schools.com
name1=value1&name2=value2
特色:
POST请求不能被缓存下来
POST请求不会保存在浏览器浏览记录中
以POST请求的URL没法保存为浏览器书签
POST请求没有长度限制
28:访问一个网站的过程
首先是查找浏览器缓存,浏览器会保存一段时间你以前访问过的一些网址的DNS信息,不一样浏览器保存的时常不等。若是没有找到对应的记录,这个时候浏览器会尝试调用系统缓存来继续查找这个网址的对应DNS信息。若是仍是没找到对应的IP,那么接着会发送一个请求到路由器上,而后路由器在本身的路由器缓存上查找记录,路由器通常也存有DNS信息。若是仍是没有,这个请求就会被发送到ISP((注:Internet Service Provider,互联网服务提供商) ,ISP也会有相应的ISP DNS服务器,若是仍是没有的话, 你的ISP的DNS服务器会将请求发向根域名服务器进行搜索。根域名服务器就是面向全球的顶级DNS服务器,共有13台逻辑上的服务器,从A到M命名,真正的实体服务器则有几百台,分布于全球各大洲。因此这些服务器有真正完整的DNS数据库。若是到了这里仍是找不到域名的对应信息,那只能说明一个问题:这个域名原本就不存在,它没有在网上正式注册过。
这也就是为何打开一个新页面会有点慢,由于本地没什么缓存,要这样递归地查询下去。
多说一句,例如"mp3.baidu.com",域名先是解析出这是个.com的域名,而后跑到管理.com域名的服务器上进行进一步查询,而后是.baidu,最后是mp3,
因此域名结构为:三级域名.二级域名.一级域名。
浏览器终于获得了IP之后,浏览器接着给这个IP的服务器发送了一个http请求,方式为get
这个get请求包含了主机(host)、用户代理(User-Agent),用户代理就是本身的浏览器,它是你的"代理人",Connection(链接属性)中的keep-alive表示浏览器告诉对方服务器在传输完如今请求的内容后不要断开链接,不断开的话下次继续链接速度就很快了。其余的顾名思义就好了。还有一个重点是Cookies,Cookies保存了用户的登录信息,在每次向服务器发送请求的时候会重复发送给服务器, 服务器收到浏览器的请求之后(实际上是WEB服务器接收到了这个请求,WEB服务器有iis、apache等),它会解析这个请求(读请求头),而后生成一个响应头和具体响应内容。接着服务器会传回来一个响应头和一个响应,响应头告诉了浏览器一些必要的信息,例如重要的Status Code,2开头如200表示一切正常,3开头表示重定向,4开头,如404,呵呵。响应就是具体的页面编码,就是那个<html>......</html>,浏览器先读了关于这个响应的说明书(响应头),而后开始解析这个响应并在页面上显示出来。
简化事后就是下面这个过程:
1.DNS域名解析:浏览器缓存、系统缓存、路由器、ISP的DNS服务器、根域名服务器。把域名转化成IP地址。
2.与IP地址对应的服务器创建TCP链接,经历三次握手:SYN,ACK、SYN,ACK
3.以get,post方式发送HTTP请求,get方式发送主机,用户代理,connection属性,cookie等
4.得到服务器的响应,显示页面
29:单点登录的原理
单点登陆在如今的系统架构中普遍存在,他将多个子系统的认证体系打通,实现了一个入口多处使用,而在架构单点登陆时,也会遇到一些小问题,在不一样的应用环境中能够采用不一样的单点登陆实现方案来知足需求。
单点登陆机制:(1);根据用户提供的登陆信息,认证系统进行身份效验,若是经过效验,应该返回给用户一个认证的凭据--ticket(2);用户再访问别的应用的时候就会将这个ticket带上,做为本身认证的凭据,应用系统接受到请求以后会把ticket送到认证系统进行效验,检查ticket的合法性。若是经过效验,用户就能够在不用再次登陆的状况下访问应用系统了。
使用cookie和session等解决也能够
30: Cookie和Session的区别
Cookies是服务器在本地机器上存储的小段文本并随每个请求发送至同一个服务器
Session机制采用的是一种在服务器端保持状态的解决方案,因为采用服务器端保持状态的方案在客户端也须要保存一个标识,因此session机制可能须要借助于cookie机制来达到保存标识的目的。而session提供了方便管理全局变量的方式 。session是针对每个用户的,变量的值保存在服务器上,用一个sessionID来区分是哪一个用户session变量,这个值是经过用户的浏览器在访问的时候返回给服务器,当客户禁用cookie时,这个值也可能设置为由get来返回给服务器。
1 .存取方式的不一样
Cookie中只能保管ASCII字符串,假如需求存取Unicode字符或者二进制数据,需求先进行编码。Cookie中也不能直接存取Java对象。
Session中可以存取任何类型的数据,包括而不限于String、Integer、List、Map等。Session中也可以直接保管Java Bean乃至任何Java类,对象等,运用起来十分便当。可以把Session看作是一个Java容器类。
2 .隐私策略的不一样
Cookie存储在客户端阅读器中,对客户端是可见的,客户端的一些程序可能会窥探、复制以致修正Cookie中的内容。而Session存储在服务器上,对客户端是透明的,不存在敏感信息泄露的风险。
3.服务器压力的不一样
Session是保管在服务器端的,每一个用户都会产生一个Session。假如并发访问的用户十分多,会产生十分多的Session,耗费大量的内存。于是像Google、Baidu、Sina这样并发访问量极高的网站,是不太可能运用Session来追踪客户会话的。
而Cookie保管在客户端,不占用服务器资源。假如并发阅读的用户十分多,Cookie是很好的选择。关于Google、Baidu、Sina来讲,Cookie或许是惟一的选择
31: 如何进行跨机房数据同步?如何保证数据访问的一致性
Master/Slave方案
这是最经常使用的方案,适用于大多数需求。Master将操做日志实时地发送到Slave,Slave当成Master的一个Hot Backup。Master宕机时,服务切换到Slave,须要修改客户端逻辑使得Master失效时自动寻找新的Master。
Zookeeper消息分发机制
32:数据库链接池
经常使用的几种链接池:DBCP、c3p0、proxool
原理:数据库链接池实际上就是在程序加载时就按照设置的数量先和数据库创建必定量的链接,当须要数据库链接时就直接从最开始创建的链接中取得所须要的链接就行。当不须要时,只须要将链接还给链接池;当创建的链接被取用完后,而且还存在后续的请求,也就是说如今的链接数量已经超过了系统设置的最大链接数。那么,后面的请求只有等待!!
33:http,socket,tcp/ip 网络传输与通信知识总结
什么是TCP和UDP,以及两者区别是什么?
TCP的全称为传输控制协议。这种协议能够提供面向链接的、可靠的、点到点的通讯。
UDP全称为用户数据报协议,它能够提供非链接的不可靠的点到多点的通讯。
使用TCP仍是UDP,那要看你的程序注重哪个方面,可靠(tcp)仍是快速(udp)。
HTTP链接
HTTP协议即超文本传送协议(Hypertext Transfer Protocol ),是Web联网的基础,也是手机联网经常使用的协议之一,HTTP协议是创建在TCP协议之上的一种应用。
HTTP链接最显著的特色是客户端发送的每次请求都须要服务器回送响应,在请求结束后,会主动释放链接。从创建链接到关闭链接的过程称为“一次链接”。
SOCKET原理
套接字(socket)是通讯的基石,是支持TCP/IP协议的网络通讯的基本操做单元。它是网络通讯过程当中端点的抽象表示,包含进行网络通讯必须的五种信息:链接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
应用层经过传输层进行数据通讯时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP链接或多个应用程序进程可能须要经过同一个 TCP协议端口传输数据。为了区别不一样的应用程序进程和链接,许多计算机操做系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应用层能够和传输层经过Socket接口,区分来自不一样应用程序进程或网络链接的通讯,实现数据传输的并发服务
创建SOCKET链接
创建Socket链接至少须要一对套接字,其中一个运行于客户端,称为ClientSocket ,另外一个运行于服务器端,称为ServerSocket 。
套接字之间的链接过程分为三个步骤:服务器监听,客户端请求,链接确认。
1.)服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待链接的状态,实时监控网络状态,等待客户端的链接请求。
2.)客户端请求:指客户端的套接字提出链接请求,要链接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要链接的服务器的套接字,指出服务器端套接字的地址和端口号,而后就向服务器端套接字提出链接请求。
3.)链接确认:当服务器端套接字监听到或者说接收到客户端套接字的链接请求时,就响应客户端套接字的请求,创建一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式创建链接。而服务器端套接字继续处于监听状态,继续接收其余客户端套接字的链接请求。
SOCKET链接与TCP/IP链接
建立Socket链接时,能够指定使用的传输层协议,Socket能够支持不一样的传输层协议(TCP或UDP),当使用TCP协议进行链接时,该Socket链接就是一个TCP链接。
SOCKET链接与HTTP链接
因为一般状况下Socket链接就是TCP链接,所以Socket链接一旦创建,通讯双方便可开始相互发送数据内容,直到双方链接断开。但在实际网络应用中,客户端到服务器之间的通讯每每须要穿越多个中间节点,例如路由器、网关、防火墙等,大部分防火墙默认会关闭长时间处于非活跃状态的链接而致使 Socket 链接断连,所以须要经过轮询告诉网络,该链接处于活跃状态。
而HTTP链接使用的是“请求—响应”的方式,不只在请求时须要先创建链接,并且须要客户端向服务器发出请求后,服务器端才能回复数据。
不少状况下,须要服务器端主动向客户端推送数据,保持客户端与服务器数据的实时与同步。
若双方创建的是Socket链接,服务器就能够直接将数据传送给客户端;
若双方创建的是HTTP链接,则服务器须要等到客户端发送一次请求后才能将数据传回给客户端。
所以,客户端定时向服务器端发送链接请求,不只能够保持在线,同时也是在“询问”服务器是否有新的数据,若是有就将数据传给客户端
实际上,传输层的TCP是基于网络层的IP协议的,而应用层的HTTP协议又是基于传输层的TCP协议的,而Socket自己不算是协议,就像上面所说,它只是提供了一个针对TCP或者UDP编程的接口。
34:设计模式
整体来讲设计模式分为三大类:
建立型模式 共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式 共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式 共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
单例模式:始终是一个对象实例.它对外不提供构造函数,所以咱们不可以同时产生多个对象.
单例模式有如下特色:
一、单例类只能有一个实例。
二、单例类必须本身建立本身的惟一实例。
三、单例类必须给全部其余对象提供这一实例。
12. }
以上懒汉式单例的实现没有考虑线程安全问题,它是线程不安全的,并发环境下极可能出现多个Singleton实例,要实现线程安全,能够在getInstance()上加同步
饿汉式单例模式
饿汉式在类建立的同时就已经建立好一个静态的对象供系统使用,之后再也不改变,因此天生是线程安全的
应用场景:常见的工具类、数据库链接类就能够定义为单例类
35:数据库 存储过程 触发器 函数
mysql 执行语句是要先编译,而后再执行的。这样若是查询并发大的时候。会浪费不少资源和时间。形成mysql进程占用资源过多,症状就是慢。但存储过程能够把一些特别的语句封装成一个方法 ,再编译好成一个能够执行的方法,对外只要接收参数就能够了。这样就不用再编译。执行就快了
何时会用到?你以为你数据库由于同时出现太多读写操做而变得慢 ,那么就要用了。
存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户经过指定存储过程的名字并给定参数(若是该存储过程带有参数)来调用执行它。
触发器是特殊的存储过程,存储过程须要程序调用,而触发器会自动执行;你所说的函数是自定义函数吧,函数是根据输入产生输出,自定义只不过输入输出的关系由用户来定义。在何时用触发器?要求系统根据某些操做自动完成相关任务,好比,根据买掉的产品的输入数量自动扣除该产品的库存量。何时用存储过程?存储过程就是程序,它是通过语法检查和编译的SQL语句,因此运行特别快。
36:数据库优化
(1) sql语句优化
不要在数据库中作运算
避免负向查询和%前缀模糊查询
不在索引列作运算或者使用函数
不要在生产环境程序中使用select * from 的形式查询数据。只查询须要使用的列
查询尽量使用limit减小返回的行数,减小数据传输时间和带宽浪费
where子句尽量对查询列使用函数,由于对查询列使用函数用不到索引
应尽可能避免在 where 子句中对字段进行 null 值判断,不然将致使引擎放弃使用索引而进行全表扫描
(2) 添加适当的索引,索引对查询速度影响很大,必须添加索引。主键索引,惟一索引,普通索引,全文索引选择适当的字段类型,特别是主键
(3) 文件、图片等大文件用文件系统存储,不用数据库
(4) 使用数据缓存
(5) 读写分离(主从数据库)
(6) 分表分区 分表:把一张大表分红多张表。分区:把一张表里面的分配到不一样的区域存储,
(7) 添加适当存储过程,触发器,事务等
37: Ajax
Ajax是(Asynchronous JavaScript And XML)是异步的JavaScript和xml。也就是异步请求更新技术。
其运行原理就至关于建立了一个请求代理,经过代理去完成与服务器的交互,交互的过程当中客户不须要等待,还能够进行其它的工做,交互完成之后,代理再将交互的结果返回给客户页面
执行步骤:
第一步:建立xmlHttpRequest对象,每一个浏览器的建立不是都相同。一般状况下为了兼容全部浏览器,每一个都要写上。
第二步:设置open()方法和setRequestHeader()方法参数。
将请求方式,请求目的地址,和请求类型设置到open方法中,若是是post请求,则须要设置setRequestHeader()参数
第三步:发送执行。利用send方法,与服务器真正的交互执行
第四步:得到执行结果。首先判断执行是否完成,而后经过js操做dom元素,将返回的responseText返回到页面
38:sql 视图和表的区别
数据库中的数据都是存储在表中的,而视图只是一个或多个表依照某个条件组合而成的结果集,通常来讲你能够用update,insert,delete等sql语句修改表中的数据,而对视图只能进行select操做
表是物理存在的,你能够理解成计算机中的文件!
视图是虚拟的内存表,你能够理解成Windows的快捷方式!
区别:一、视图是已经编译好的sql语句。而表不是
二、视图没有实际的物理记录。而表有。
三、表是内容,视图是窗口
四、表只用物理空间而视图不占用物理空间,视图只是逻辑概念的存在,表能够及时对它进行修改,但视图只能有建立的语句来修改
五、表是内模式,视图是外模式
六、视图是查看数据表的一种方法,能够查询数据表中某些字段构成的数据,只是一些SQL语句的集合。从安全的角度说,视图能够不给用户接触数据表,从而不知道表结构。
七、表属于全局模式中的表,是实表;视图属于局部模式的表,是虚表。
八、视图的创建和删除只影响视图自己,不影响对应的基本表。
使用视图的好处:
第一点:使用视图,能够定制用户数据,聚焦特定的数据。
第二点:使用视图,能够简化数据操做。
第三点:使用视图,基表中的数据就有了必定的安全性
第四点:能够合并分离的数据,建立分区视图
39:CSS相关 盒子模型
Div居中:margin:0 auto; 在添加一个宽度
40:服务器端开发须要的知识点
多进程、多线程:
进程优势:编程、调试简单,可靠性较高。
进程缺点:建立、销毁、切换速度慢,内存、资源占用大。
线程优势:建立、销毁、切换速度快,内存、资源占用小。
线程缺点:编程、调试复杂,可靠性较差。
socket开发模型
socket通讯在客户端和服务器端进行,主要包括
服务器端行为:
1:服务器端建立套接字,s = socket.socket() ; 2:绑定套接字到本地ip和端口号, s.bind(ip_port); 3:监听链接, s.listen(n);4:接受客户端创建链接的请求,conn,addr = s.accept(); 5:接受客户端的消息,并作出相应处理 recv_data = conn.recv(1024); 6 : 给客户端回消息,conn.send(send_data); 7:关闭链接;
客户端行为:
1:建立套接字; 2:链接服务器; 3:给服务器发消息; 4:接受服务器消息; 5:关闭链接;
SocketServer实现支持多客户端
SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的Socket服务端。即:每一个客户端请求链接到服务器时,Socket服务端都会在服务器是建立一个“线程”或者“进程” 专门负责处理当前客户端的全部请求
分布式系统概念
1. 熟悉Unix/Linux系统者优先;
2. 熟悉Shell脚本者优先。
41:linux下进程间的通讯
方法:管道、消息队列、共享内存、信号量、套接口等等
共享内存:共享内存是运行在同一台机器上的进程间通讯最快的方式,由于数据不须要在不一样的进程间复制。一般由一个进程建立一块共享内存区,其他进程对这块内存区进行 读写
42:乐观锁/悲观锁
悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,因此每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了不少这种锁机制,好比行锁,表锁等,读锁,写锁等,都是在作操做以前先上锁。
乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,因此不会上锁,可是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可使用版本号等机制。乐观锁适用于多读的应用类型,这样能够提升吞吐量,像数据库若是提供相似于write_condition机制的其实都是提供的乐观锁。
两种锁各有优缺点,不可认为一种好于另外一种,像乐观锁适用于写比较少的状况下,即冲突真的不多发生的时候,这样能够省去了锁的开销,加大了系统的整个吞吐量。但若是常常产生冲突,上层应用会不断的进行retry,这样反却是下降了性能,因此这种状况下用悲观锁就比较合适。
43:java中实现同步的几种方法
1:同步方法
即有synchronized关键字修饰的方法。
因为java的每一个对象都有一个内置锁,当用此关键字修饰方法时,
内置锁会保护整个方法。在调用该方法前,须要得到内置锁,不然就处于阻塞状态。
例子:public synchronized void save(){}
2:同步代码块
即有synchronized关键字修饰的语句块。
被该关键字修饰的语句块会自动被加上内置锁,从而实现同步
例子:synchronized(object){
}
3:Lock接口
1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;
2)synchronized在发生异常时,会自动释放线程占有的锁,所以不会致使死锁现象发生;而Lock在发生异常时,若是没有主动经过unLock()去释放锁,则极可能形成死锁现象,所以使用Lock时须要在finally块中释放锁;
3)Lock可让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不可以响应中断;
4)经过Lock能够知道有没有成功获取锁,而synchronized却没法办到。
5)Lock能够提升多个线程进行读操做的效率。