HashMap 和 Hashtable 的区别
1.hashMap去掉了HashTable 的contains方法,但是加上了containsValue()和containsKey()方法。
2.hashTable同步的,而HashMap是非同步的,效率上逼hashTable要高。
3.hashMap允许空键值,而hashTable不允许。
4.初始size为16,扩容:newsize = oldsize2,size一定为2的n次幂
初始size为11,扩容:newsize = olesize2+1
HashMap 和 ConcurrentHashMap 的区别
ConcurrentHashMap是线程安全的HashMap的实现。
底层采用分段的数组+链表实现,线程安全
通过把整个Map分为N个Segment,可以提供相同的线程安全,但是效率提升N倍,默认提升16倍。(读操作不加锁,由于HashEntry的value变量是 volatile的,也能保证读取到最新的值。)
Hashtable的synchronized是针对整张Hash表的,即每次锁住整张表让线程独占,ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术
map遍历方法
1、Iterator遍历
Iterator<Map.Entry<String,String>> it = map.entrySet().iterator();
while(it.hasNext()){
Map.Entry<String,String> entry=it.next();
System.out.println("key=" +entry.getKey() +" and value="+entry.getValue());
}
2、取值遍历
for(String key:map.keySet()){
System.out.println("key="+key+"and value=" +map.get(key));
}
3、遍历所有的Value值
该方式取得不了key值,直接遍历map中存放的value值
for(String v:map.values()){
System.out.println("value= "+ v);
}
4、使用entrySet遍历
for(Map.Entry<String,String > entry:map.entrySet()){
System.out.println("key=" +entry.getKey() +" and value="+entry.getValue());
}
List遍历:for,foreach Iterator 速度比较
如果是ArrayList,用三种方式遍历的速度是for>Iterator>foreach,速度级别基本一致;
如果是LinkedList,则三种方式遍历的差距很大了,数据量大时越明显(一般是超过100000级别),用for遍历的效率远远落后于foreach和Iterator,Iterator>foreach>>>for;
1:测试发现foreach和Iterator基本上都在一个速度级别,但Iterator会稍稍快于foreach,事实上,foreach就是基于Iterator实现的,可通过反编译工具看到。
所以foreach和Iterator基本是效率相当的,慢的时间猜测就是foreach隐式转换成Iterator所消耗的时间.
2:接下来要解释的是为什么ArrayList的遍历中for比Iterator快,而LinkedList中却是Iterator远快于for?这得从ArrayList和LinkedList两者的数据结构说起了:
ArrayList是基于索引(index)的数组,索引在数组中搜索和读取数据的时间复杂度是O(1),但是要增加和删除数据却是开销很大的,因为这需要重排数组中的所有数据。
LinkedList的底层实现则是一个双向循环带头节点的链表,因此LinkedList中插入或删除的时间复杂度仅为O(1),但是获取数据的时间复杂度却是O(n)。
明白了两种List的区别之后,就知道,ArrayList用for循环随机读取的速度是很快的,因为ArrayList的下标是明确的,读取一个数据的时间复杂度仅为O(1)。但LinkedList若是用for来遍历效率很低,读取一个数据的时间复杂度就达到了为O(n)。而用Iterator的next()则是顺着链表节点顺序读取数据的效率就很高了。
最后总结:
1:ArrayList用三种遍历方式都差得不算太多,一般都会用for或者foreach,因为Iterator写法相对复杂一些。
2:LinkedList的话,推荐使用foreach或者Iterator(数据量越大时,三者方法差别明显)。
PS:
Iterator实例化方法
Iterator iterator = list.iterator()
while(iterator.hasNext()){
T t = iterator.next();
System.out.println(t);
}
tomcat配置,项目请求路径的配置,端口号的配置
conf目录下 server.xml
tomcat热部署和热加载
文件服务器的搭建
public private protect的权限区别
hibernate和mybatis的缓存机制
hibernate
一级缓存(session级别)
二级缓存(sessionFactory级别)
hibernate
分为一级缓存即session缓存也叫事务级别的缓存
二级缓存sessionFactory即应用级别的缓存
三级缓存即查询缓存。
mybatis
一级缓存是SqlSession级别的缓存,缓存的数据只在SqlSession内有效
二级缓存是mapper级别的缓存,同一个namespace公用这一个缓存,所以对SqlSession是共享的
spring的依赖注入有几种
注解注入方式、set注入方式、构造器注入方式、静态工厂注入方式
myBatis的$和#
#可以防止Sql 注入,它会将所有传入的参数作为一个字符串来处理。
$ 则将传入的参数拼接到Sql上去执行,一般用于表名和字段名参数,$ 所对应的参数应该由服务器端提供,前端可以用参数进行选择,避免 Sql 注入的风险
@Autowired与@Resource的区别
@pathvariable @RequestBody的区别
@requestparam
spring配置的bean类怎么调用
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) context.getBean("user");
JSP和Servlet有哪些相同点和不同点,他们之间的联系是什么?
zookeeper的选取leader 原理
kafka的运行的机制
java线程池的了解
ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
BlockingQueue workQueue);
synchronized和lock锁的区别,重入锁 (需要手动释放)
两者区别:
1.首先synchronized是java内置关键字,在jvm层面,Lock是个java类;
2.synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;
3.synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;
4.用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2线程等待。如果线程1阻塞,线程2则会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了;
5.synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可中断、可公平(两者皆可)
6.Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。
乐观锁和悲观锁
volatile可以保证线程安全吗?手写了个例子验证一下
线程池发生死锁的情况
死锁的根本原因1)是多个线程涉及到多个锁,这些锁存在着交叉,所以可能会导致了一个锁依赖的闭环;2)默认的锁申请操作是阻塞的。所以要避免死锁,就要在一遇到多个对象锁交叉的情况,就要仔细审查这几个对象的类中的所有方法,是否存在着导致锁依赖的环路的可能性。要采取各种方法来杜绝这种可能性。
request 用户端请求,此请求会包含来自GET/POST请求的参数
response 网页传回用户端的回应
session 与请求有关的会话期
application servlet 正在执行的内容
out 用来传送回应的输出
exception 针对错误网页,未捕捉的例外
page JSP网页本身
pageContext 网页的属性是在这里管理
exception 针对错误网页,未捕捉的例外
config servlet的构架部件
jdbc的流程
1、 加载JDBC驱动程序:
2、 提供JDBC连接的URL
3、创建数据库的连接
4、创建一个Statement
5、执行sql
要连接数据库,需要向java.sql.DriverManager请求并获得Connection对象, 该对象就代表一个数据库的连接。
使用DriverManager的getConnectin(String url , String username , String password )方法传入指定的欲连接的数据库的路径、数据库的用户名和 密码来获得。
MySql和Orcale的分页
mysql --> limit(n,m) 两个参数的意义
oracle–> rownum
Hibernate --> setfirstResult(),setMaxResult()
sql查询(批量插入,批量更新)
insert into student values
(1,小明),(2,小黄),(3,小天)
更新多条记录的同一个字段为同一个值
UPDATE course SET name=‘course1’ WHERE id in(‘id1’,‘id2’,'id3);
更新多条记录为多个字段为不同的值
MySQL没有提供直接的方法来实现批量更新,但可以使用case when语法来实现这个功能。
UPDATE course
SET name = CASE id
WHEN 1 THEN ‘name1’
WHEN 2 THEN ‘name2’
WHEN 3 THEN ‘name3’
END,
title = CASE id
WHEN 1 THEN ‘New Title 1’
WHEN 2 THEN ‘New Title 2’
WHEN 3 THEN ‘New Title 3’
END
WHERE id IN (1,2,3)
case when then end可用于sql行列互换查询
题目:数据库中有一张如下所示的表,表名为sales。
年 季度 销售量
1991 1 11
1991 2 12
1991 3 13
1991 4 14
1992 1 21
1992 2 22
1992 3 23
1992 4 24
要求:写一个SQL语句查询出如下所示的结果。
年 一季度 二季度 三季度 四季度
1991 11 12 13 14
1992 21 22 23 24
我给出的答案是这样的:
select 年,
sum(case when 季度=1 then 销售量 else 0 end) as 一季度,
sum(case when 季度=2 then 销售量 else 0 end) as 二季度,
sum(case when 季度=3 then 销售量 else 0 end) as 三季度,
sum(case when 季度=4 then 销售量 else 0 end) as 四季度
from sales group by 年;
集群和分布式的关系
简单的解释:
小饭店原来只有一个厨师,切菜洗菜备料炒菜全干。后来客人多了,厨房一个厨师忙不过来,又请了个厨师,两个厨师都能炒一样的菜,这两个厨师的关系是集群。为了让厨师专心炒菜,把菜做到极致,又请了个配菜师负责切菜,备菜,备料,厨师和配菜师的关系是分布式,一个配菜师也忙不过来了,又请了个配菜师,两个配菜师关系是集群
负载均衡的几种常用方式
1、轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
upstreambackserver {
server192.168.0.14;
server192.168.0.15;
}
2、weight
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的
情况。
upstreambackserver {
server192.168.0.14weight= 3;
server192.168.0.15weight= 7;
}
权重越高,在被访问的概率越大,如上例,分别是30%,70%。
3、上述方式存在一个问题就是说,在负载均衡系统中,假如用户在某台服务器上登录了,那么该用户第二次请求的时候,因为我们是负载均衡系统,每次请求都会重新定位到服务器集群中的某一个,那么已经登录某一个服务器的用户再重新定位到另一个服务器,其登录信息将会丢失,这样显然是不妥的。
我们可以采用ip_hash指令解决这个问题,如果客户已经访问了某个服务器,当用户再次访问时,会将该请求通过哈希算法,自动定位到该服务器。
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
upstream backserver {
ip_hash;
server192.168.0.14: 88;
server192.168.0.15: 80;
}
4、fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
upstream backserver {
serverserver1;
serverserver2;
fair;
}
5、url_hash(第三方)
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
upstreambackserver {
serversquid1: 3128;
serversquid2: 3128;
hash$request_uri;
hash_methodcrc32;
}