阿里一面
1 arraylist扩容机制
http://blog.csdn.net/huangfan322/article/details/52685922
ArrayList底层采用Object类型的数组实现.当使用不带参数的构造方法生成ArrayList对象时,实际上会在底层生成一个长度为10的Object类型数组。 默认容量为10.
private static final int DEFAULT_CAPACITY = 10;
transient Object[] elementData;
ArrayList是关于数组的系统的方法组合。
java设置了最小容量(minCapacity),通常情况上,它大于列表对象的数目。Capactiy虽然就是底层数组的长度(length),但是对于最终用户来讲,它是无意义的。而size存储着列表对象的数量,才是最终用户所需要的。
capacity可以自己指定,不指定默认是10.
通过以上代码,我们可知java自动增加ArrayList大小的思路是:add()方法向ArrayList添加对象时,原对象数目加1如果大于原底层数组长度,则以适当长度(原来数组容量的1.5倍)新建一个原数组的拷贝,并修改原数组,指向这个新建数组。原数组自动抛弃(java垃圾回收机制会自动回收)。size则在向数组添加对象,自增1。
remove:数组前移一位,size自减,空出来的位置置null,具体的对象的销毁由Junk收集器负责。
2 linkedlist与arraylist区别
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 (LinkedList是双向链表,有next也有previous)
2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
3 分布式session一致性
服务器之间相互复制。占用内网的带宽。存所有服务器的session内存受限。
存在用户浏览器的cookie中。
反向代理?
使用第三方服务器,redis缓存作为session的集中管理。或者直接存在数据库中。
4 volatile 原理 使用场景
多线程场景。
解决可见性的问题。
线程A
本地内存A 存储线程的局部变量。复制主存的共享变量作为本地
的副本,目的是为了减少和主存通信的频率,提高效率。
主内存。存储类成员变量等
局部变量不存在可见性问题,而共享内存就会有可见性问题,因为本地线程在创建的时候,会从主存中读取一个共享变量的副本,且修改也是修改副本,且并不是立即刷新到主存中去,那么其他线程并不会马上共享变量的修改。 因此,线程B修改共享变量后,线程A并不会马上知晓,就会出现上述死循环的问题。
解决共享变量可见性问题,需要用volatile关键字修饰。
可见性的特性总结为以下2点:
1. 对volatile变量的写会立即刷新到主存
2. 对volatile变量的读会读主存中的新值
5 concurrenthashmap jdk1.8
concurrentHashMap在1.8中的实现,相比于1.7的版本基本上全部都变掉了。首h先,取消了Segment分段锁的数据结构,取而代之的是数组+链表(红黑树)的结构。将原先table数组+单向链表的数据结构,变更为table数组+单向链表+红黑树的结构。而对于锁的粒度,调整为对每个数组元素加锁(Node)。然后是定位节点的hash算法被简化了,这样带来的弊端是Hash冲突会加剧。因此在链表节点数量大于8时,会将链表转化为红黑树进行存储。这样一来,查询的时间复杂度就会由原先的O(n)变为O(logN)。
6 单例模式哪几种
第二种(懒汉,线程安全):
public class SingletonDemo2 {
private static SingletonDemo2 instance;
private SingletonDemo2(){}
public static synchronized SingletonDemo2 getInstance(){
if (instance == null) {
instance = new SingletonDemo2();
}
return instance;
}
}
去掉锁就是一种不安全的了。
第三种(饿汉):
public class SingletonDemo3 {
private static SingletonDemo3 instance = new SingletonDemo3();
private SingletonDemo3(){}
public static SingletonDemo3 getInstance(){
return instance;
}
}
这种方式基于classloder机制避免了多线程的同步问题,不过,instance在类装载时就实例化,这时候初始化instance显然没有达到lazy loading的效果。
7 枚举原理
枚举本质上是通过普通的类来实现的,只是编译器为我们进行了处理。每个枚举类型都继承自java.lang.Enum,并自动添加了values和valueOf方法。而每个枚举常量是一个静态常量字段,使用内部类实现,该内部类继承了枚举类。所有枚举常量都通过静态代码块来进行初始化,即在类加载期间就初始化。另外通过把clone、readObject、writeObject这三个方法定义为final的,同时实现是抛出相应的异常。这样保证了每个枚举类型及枚举常量都是不可变的。可以利用枚举的这两个特性来实现线程安全的单例。
8 多线程状态
新建状态、就绪状态(缺cpu)、运行状态、阻塞状态(缺其他资源)及死亡状态。
9 两次调用start方法会怎样
IllegalThreadStateException
10 事务
事务ACID
原子性 事务是最小单位 把-100 +100 包装在一个事务中
一致性 从一个一致性状态转移到另一个一致性状态
隔离性 事务在提交之前是不被其他事务可见的
持久性 事务一旦被提交 就会被永久存在数据库中
事务的隔离级别 四种
未提交读
提交读即不可重复读 提交后才可以读 大部分数据库
可重复读 解决了脏读 mysql
可串行化 解决了幻读
11 执行事务是在同一个数据库连接中吗
一个事务是需要在一次连接中完成的。一次连接中可以处理多个事务。
12 spring如何处理事务
https://www.cnblogs.com/mxmbk/p/5341258.html
13 索引 聚簇索引和非聚簇索引
索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息。建立索引的目的是加快对表中记录的查找或排序。
InnoDB使用的是聚簇索引,由于聚簇索引规定数据在表中的物理存 储顺序,因此一个表只能包含一个聚簇索引。比如主键。
MyISAM的是非聚簇索引,表数据存储顺序与索引顺序无关。
14 jvm内存结构
程序计数器、Java虚拟机栈、本地方法栈、堆、方法区、字符串常量池
15 堆结构
survivor Eden 1:8
16 jdbc步骤
JDBC编程的六个步骤: 准备工作中导入ojdbc文件,然后右键选中添加路径 build path-->到oracle安装目录里添加oracle的ojdbc.jar包 (1).注册驱动 Class.forName("oracle.jdbc.OracleDriver"); (2).连接数据库 String url = "jdbc:oracle:thin:@localhost:1521:xe";//其中xe为sid String user = "XXX"; String password = "XXX"; Connection conn = DriverManager.getConnection(url,name,password); (3).创建搬运工statement Statement state = conn.createStatement(); (4).搬运数据,执行SQL语句 String sql = "select id,name from s_emp"; //"insert into s_emp(id,name) values(12,'zhangsan')"; ResultSet rs = state.executeQuery(sql); (5).处理结果集 while(rs.next()){ int id = rs.getInt("id"); String name = rs.getString(2); System.out.println(id+" "+name); } (6).关闭连接 rs.close(); state.close(); conn.close();
如下面所示代码,实现插入操作
[java] view plain copy
1. public void test_insert()
2. {
3. String driver="oracle.jdbc.driver.OracleDriver";
4. String url="jdbc:oracle:thin:@127.0.0.1:1521:orcl";//orcl为sid
5. String user="briup";
6. String password="briup";
7. Connection conn=null;
8. Statement stat=null;
9. try {
10. //1、注册驱动
11. Class.forName(driver);
12. //2、获取连接
13. conn= DriverManager.getConnection(url, user, password);
14. //System.out.println(conn);
15. //3、创建statement对象
16. stat=conn.createStatement();
17. //4、执行sql语句
18. String sql="insert into lover values(5,'suxingxing',to_date('21-9-2016','dd-mm-yyyy'))";
19. stat.execute(sql);
20. //System.out.println(stat.execute(sql));
21. //5、处理结果集,如果有的话就处理,没有就不用处理,当然insert语句就不用处理了
22. } catch (Exception e) {
23. e.printStackTrace();
24. }
25. finally{
26. //6、关闭资源
27. try {
28. if(stat!=null)stat.close();
29. } catch (SQLException e) {
30. e.printStackTrace();
31. }
32. try {
33. if(conn!=null)conn.close();
34. } catch (SQLException e) {
35. e.printStackTrace();
36. }
37. }
38. }