面试题集锦1

1.准备自我介绍
2.dubbo踩过的坑?
版本兼容问题
比如说dubbo2.7.1只支持jdk8
3.自定义异常拦截器
4.谈谈线程安全?
进程的概念
线程的概念
线程安全:当多个线程访问某个方法时,我们在主程序中不需要去做任何的同步,这个类的结果行为就是我们设想的正确行为,那么我们就说这个类是线程安全的。
保证线程安全的方法
1).竞争与原子操作
2)同步与锁
3)可重入(并发安全的强力保障)
4)过度优化(volatile)
第一阻止编译器为了提高速度将一个变量缓存到寄存器而不写回
第二阻止编译器调整操作volatile变量的指令顺序

5事务的四个特性
原子性 持久性 隔离性 一致性
原子性:事务开始后的操作要么全部做完 要么全部不做 不可能停滞在中间环节
持久性:事务完成后 事务对数据库的所有更新被保留到数据库 不能回滚
隔离性:同一个时间只允许一个事务请求同一个数据 不同事务之间彼此没有任何干扰
一致性:事务开始前和结束后 数据库的完整性约束没有被破坏

6.乐观锁和悲观锁的区别
读取频繁用乐观锁
写入频繁用悲观锁
update table set x=x+1,version=version+1 where id=#{id} and version=#{version};

悲观锁 synchronize 先自旋后阻塞 不会占用CPU资源
7.HashMap是线程安全的吗?为什么?那些是线程安全的容器?以及HashMap与HashTable的区别?

HashMap不是线程安全的 hashmap做put操作时 两个线程同时进入addEntry()操作时 计算出相同的hash值
ab线程都会写入头节点 a的操作会被覆盖 造成a的操作丢失
vector hashtable concurrenthashmap copyonwriteArrayList

1)继承不同 hashtable继承Dictionary类 hashmap继承abstract类
hashtable中方法是同步的 hashmap是非同步的
hashtable的实现方法里面添加了synchronize关键字来确保同步
使用hashmap的话就要自己增加同步处理 同步方法Map m=Collections.synchronizeMap(hashmap);
2)hashtable中的kv都不允许出现null hashmap中null可以作为键只有一个为null的值可以有一个或者多个(hashmap中不能用get()判断是否存在某个键 应该用containsKey() )
3)遍历方式。hashmap/hashtable都使用了Iterator
4)hash值得使用不同 hashtable直接使用对象的hashcode hashmap重新计算hash值
5)数组的初始大小和扩容方式不同 hashtable的数组默认大小是11 扩容方式是old*2+1
hashmap中默认大小是16 扩容方式是2的指数次幂
6)求数组下标方式不同 hashtable通过除以length取余 hashmap是与length-1 进行按位与运算

8.jdk1.8对ConcurrentHashMap做了哪些优化?为什么这样优化?
1)取消segments字段 直接采用transient volatile HashEntry<K,V> table 保存数据 采用table数组元素作为锁从而实现对每一行数据进行加锁 进一步减少并发冲突的概率
2)将原先table数组 +单向链表的数组结构变更为table数组+单向链表+红黑树的结构 对于hash表来说 最核心的能力在于将key hash之后能均匀分布在数组中 如果hash之后散列的很均匀 那么table数组中的每个队列长度主要为0或1 但实际情况并没有如此理想 虽然ConcurrentHashMap类默认的加载因子为0.75 但是在数据量过大或者运气不佳的情况下 还是会存在一些队列长度过长的情况 如果还是采用单向列表方式 那么查询某个节点的时间复杂度为O(n)因此 对于个数超过8的列表 jdk8采用了红黑树结构 那么查询的时间复杂度可以降低到O(logN)可以改进性能。
注:在1.8中ConcurrentHashMap的get操作全过程不需要加锁 这也是它比其他并发集合比如hashtable。用Collections.synchronizedMap()包装的hashmap安全效率高的原因之一。
get操作全程不需要加锁是因为Node的成员val是用volatile修饰的和数组用volatile修饰没有关系

数组用volatile修饰主要是保证在数组扩容的时候保证可见性。
segment:可重入锁(在java环境下ReentrantLock和synchronized都是可重入锁)继承ReentrantLock,也称之为桶
9.redis主从机制了解么?怎么实现的?
主从复制,是将一台redis服务器的数据,复制到其他的redis服务器 前者称为主节点(master)后者称为从节点(slave);
作用:数据冗余 故障恢复 负载均衡 高可用
10.分布式中的CAP原理
一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项。
https://blog.csdn.net/w372426096/article/details/80437198

11.List,Map,Set三个接口存取元素时,各有什么特点?
首先 List与set具有相似性 他们都是单列元素的集合 所以 它们有一个共同的父接口,叫Collection set里面不允许有重复的元素 set取元素 只能以Iterator接口取得所有的元素 再逐个遍历
List表示有先后顺序的集合 所以可以用get(index i)明确取第几个

Map与List和set不同 他是双列的集合 其中有put方法 每次存储都是kv键值对不能存重复的key
List以特定次序来持有元素 可有重复元素 Set无法拥有重复元素,内部排序
hashset按照hashcode值得某种运算方式进行存储 而不是按hashcode值得大小进行存储
LinkHashSet按插入顺序存储

12.TreeMap和TreeSet在排序时如何比较元素?Collection工具类中的sort()方法如何比较元素?

TreeMap
其放入键值对的键必须实现Comparable接口
然后根据其compareTo()方法,进行排序
TreeSet
使用自然排序
元素所属的类实现Comparable接口重写compareTo(T o)方法
然后在compareTo()中根据主要和次要进行编写的排序规则产生返回值
根据compareTo()的返回值,判断当前元素是否大于或小于比较的元素
比较器Comparator
根据TreeSet构造器传入的比较器中重写的compare(T o1,T o2)方法
根据传入的返回值判断比较结果
使用add()方法会自动调用compare()方法

使用自定义类型的集合进行排序
使用自然排序
元素所属的类实现Comparable接口 重写compareTo(T o)方法
然后在compareTo()中根据主要和次要进行编写排序规则 产生返回值
根据compareTo()的返回值 判断当前元素是否大于或者小于比较的元素
比较器comparator
根据TreeSet构造器传入的比较器中重写的compare(T o1,T o2)方法
根据传入的返回值判断比较结果
使用包装类等
根据其实现Comparable接口中comparareTo()方法
进行比较排序

13Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行 它们有什么区别?
sleep是Thread的静态native方法 可随时调用 会使当前线程休眠并释放cpu资源但不会释放对象锁
wait()是Object的本地方法,只能在同步方法或者同步代码块中使用 调用会进入休眠状态并释放cpu资源与对象锁 需要我们调用notify、notifyAll方法唤醒指定或者全部的休眠线程再次竞争cpu资源

14.线程的sleep()方法和yield()方法有什么区别?
sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会
yield()方法只会给相同优先级或者更高优先级的线程以运行的机会
线程执行sleep()方法后转入阻塞(blocked)状态而在执行yield()方法后转入就绪(ready)状态
sleep()方法声明会抛出InterruputedException,而yield()方法没有声明任何异常
sleep()方法比yield()方法具有更好的移植性

15.当一个线程进入一个对象的synchronized方法A之后 其他线程是否可进入此对象的synchronized方法b?
不能 其他线程只能访问该对象的非同步方法 同步方法则不能进入因为非静态方法上的synchronized修饰符要求执行方法时要获得对象的锁 如果已经进入A方法说明对象锁已经被取走那么试图进入B方法的线程就只能在等锁池中等待对象的锁。

16.请说出与线程同步以及线程调度相关的方法
sleep 使线程睡眠 调用此方法要处理InterruptedException异常
wait 使线程进入阻塞状态 并释放所持有对象的锁
notity()唤醒一个等待状态的线程
notifyAll() 唤醒所有处于等待的线程该方法并不是将对象的锁给所有线程 而是让他们竞争 只有获得锁的线程才能进入就绪状态

17.synchroized关键字的用法?

https://www.cnblogs.com/wl0000-03/p/5973039.html

java内置锁:每个java对象都可以用作内置锁(互斥)
java的对象锁和类锁:对象锁用于对象的实例化方法或者一个对象实例上的
类锁是用于类的静态方法或者一个类的class对象上的
类锁是概念上的
对象锁的synchronized修饰方法和代码块

18.启动一个线程是调用run()还是start()方法?

启动一个线程是调用start()方法 使线程所代表的虚拟处理机处于可运行状态 这意味着它可以由JVM调度并执行 这不意味着线程就会立即运行
当cpu分配给它时间时,才开始执行run()方法(如果有的话)。START()是方法,它调用RUN()方法.而RUN()方法是你必须重写的.
run()方法是线程启动后要进行回调(callback)的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值