oppo面试题
1、synchronized和Lock有什么区别?哪个可重入?哪个效率高?
synchronized和Lock都用于线程同步的场景中。
synchronized是jdk的关键字,用来构造同步代码块或者同步方法。同步代码块的锁是synchronized括号中的对象,同步方法的锁是当前类实例或者当前类的Class实例,取决于同步方法是实例方法还是静态方法。如果一个线程获得锁,那么就执行同步代码块或者同步方法。如果不能获取锁,那么线程会阻塞,直到获取锁,然后执行同步代码块或者同步方法。synchronized的锁不用我们写代码手动释放,在同步代码块或者同步方法执行完毕或抛异常的情况下会自动释放锁。
Lock是jdk的一个接口,常用实现类是ReentrantLock。Lock有4个获取锁的方法:
void lock():锁被另一个线程持有的话,当前线程会一直阻塞,直到获取锁。
void lockInterruptibly() throws InterruptedException:锁被另一个线程持有的话,当前线程会一直阻塞,直到获取锁或者被其他线程中断。
boolean tryLock():返回boolean类型。如果获取到锁的话,就返回true,否则返回false。线程不会阻塞。
boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException:锁被另一个线程持有的话,当前线程会一直阻塞,直到获取锁或者到指定时间或者被其他线程中断。
其实,只有tryLock()无参方法会直接返回,另外3个方法都会阻塞线程。
锁不会自动释放,即使抛异常,所以我们必须写代码手动释放锁。调用unlock()方法释放锁,且必须写在finally块中,防止抛异常而执行不到。
调用Lock实例的newCondition()方法可生成Condition实例,Condition实例的await()方法会使调用线程释放锁并进入该Condition实例的等待队列中,而signal()方法会唤醒等待在当前Condition实例上的一个线程,await()方法、signal()方法配合使用,可以实现线程间通信。一个Lock实例又可生成多个Condition实例,多个Condition实例配合使用,可以实现多个线程按照一定顺序执行的效果。
synchronized是非公平锁。ReentrantLock既可以公平,又可以非公平,取决于构造器传参,默认是非公平锁,效率比公平锁要高。公平锁就是说获得锁的线程遵循先来后到的原则,而非公平锁对线程先后顺序无所谓。
synchronized是可重入的,如创建单例时就有一种双检锁模式,同步代码块或者同步方法执行完后,不管获取了几次锁,锁都释放了。Lock的实现类ReentrantLock也是可重入锁,同一个线程可以多次获取到这个锁,释放锁的时候必须释放多次,unlock()方法执行次数必须与各种lock()方法执行次数一样,否则锁释放不掉。
ReentrantLock内部是用AQS实现的。在各种lock()方法中均调用了AQS的compareAndSetState()方法,而compareAndSetState()方法内部调用的是Unsafe(全类名是sun.misc.Unsafe)实例的CompareAndSwapInt()native方法。
2、CAS、AQS
CAS:compareAndSwap的简称,比较并替换,是实现并发算法时常用的一种技术。AQS和原子类(AtomicInteger、AtomicBoolean等Atomic开头的类)的实现,大量使用了CAS。
CAS有3个操作数:当前内存值、预期值、要修改的新值。比较内存值和预期值,如果相等,就把值设为新值,返回true,否则什么都不做,返回false。CAS实际上是利用处理器提供的CMPXCHG指令实现的,处理器执行CMPXCHG指令是原子操作。
CAS最大的问题是ABA问题。CAS在操作值的时候会检查下值有没有发生变化,如果没有发生变化则更新,但是如果一个值原来是A,变成了B,又变成了A,那么使用CAS进行检查时会发现它的值没有发生变化,但是实际上却变化了。这就是CAS的ABA问题。常见的解决思路是使用版本号。在值前面追加上版本号,每次变量更新的时候把版本号加1,那么A-B-A 就会变成1A-2B-3A。
AQS见另一篇文章:https://www.cnblogs.com/koushr/p/5873444.html
3、ConcurrentHashMap怎么实现的?
从jdk1.8开始,ConcurrentHashMap采用CAS+synchronized来保证并发更新的安全,底层是数组+链表+红黑树的存储结构。
在首次put时要调用initTable()方法初始化Node数组(Node有4个成员变量:int hash,K key,volatile V value,volatile Node<K, V> next),initTable()方法中用了CAS,保证在多线程情况下只有一个线程会创建Node数组。
根据key的hash值找到在Node数组中的位置,如果该位置处的元素为null,说明这个位置还没插入元素,则利用Unsafe的compareAndSwapObject实例方法插入Node节点。如果CAS成功,则Node节点正常插入,否则表示有其它线程提前插入了节点,当前线程自旋重新尝试在这个位置插入节点。
在put一个重复key或者一个hash值和现在某个key的hash值一样的key时,putVal()方法会执行一个同步代码块,这个同步代码块的锁是ConcurrentHash实例key对应的Node实例,如此同时只有一个线程可以去更新value或者在链表中新增一个Node节点。
4、垃圾回收器有哪些?有什么不同?
5、postgresql相对于mysql有什么优点?
1)pg在GIS领域绝对领先。
2)pg支持窗口函数或者说是分析函数。而mysql直到8才支持,5.7及以前都不支持。
3)pg原生支持递归查询,用with recursive即可,而mysql没那么简单,需要自己写存储过程。
4)pg支持表达式索引和条件索引。mysq不支持。
表达式索引:
筛选条件是where lower(name) = 'zhangsan';
如果在name列上加索引,查询语句肯定是不会走此索引的。所以可以给lower(name)加索引,脚本如下:
create index idx_lvl_trace_info_name_lower on lvl_trace_info(lower(name));
条件索引:
create index idx_lvl_trace_info_updated_date_2019 on lvl_trace_info(updated_date) where updated_date > '2019-01-01 00:00:00';
则下面语句会走索引
select * from lvl_trace_info where updated_date between '2019-01-01' and '2019-06-01';
而下面语句不会走索引
select * from lvl_trace_info where updated_date between '2018-01-01' and '2019-01-01';
5)pg原生支持存储emoji。而mysql需要指定字符集是utf8mb4,才能存储emoji。
6)mysql文本类型有tinytext、text、mediumtext、longtext,分别可支持不同长度的文本,在用的时候,需要我们预估文本长度,然后选择一个合适的类型。而pg文本类型没有那么多,只有一个text,可以支持任意长度,方便使用。
7)mysql可以通过select @@global.tx_isolation;及select @@tx_isolation;查看全局和当前会话的事务隔离级别。mysql的默认事务隔离级别是repeatable-read。
pg可以通过show default_transaction_isolation;及show transaction_isolation;查看默认事务隔离级别和当前会话事务隔离级别。
6、mysql主键索引和二级索引有什么区别?
InnoDB引擎的mysql,主键索引是聚簇索引,索引数据和行数据都存储在同一个B+树中。该B+树根据索引数据进行创建,数据存储在叶子节点中。数据的物理顺序和索引逻辑顺序一致。一个表最多只能有一个聚簇索引,因为数据物理顺序不可能有多个顺序。
二级索引,如普通索引、唯一索引、复合索引,是非聚簇索引。非聚簇索引,索引和数据分开存储。索引B+树只存储索引数据及其与主键的映射。
举个例子,表lvl_trace_info有主键字段id,普通索引字段updated_date,及其他。
根据主键id的查询语句:
select * from lvl_trace_info where id = 99;
这个查询语句会去主键索引树上查数据,因为行数据存储在叶子节点上,所以一下子就把数据查出来了。
根据普通索引列updated_date的查询语句:
select * from lvl_trace_info where updated_date > current_date;
这个查询语句会去updated_date对应的二级索引数上查找满足updated_date > current_date的updated_date对应的主键id,然后再根据这些主键id去主键索引树上查找对应的行数据。总结起来,需要先查询二级索引树,再查询主键索引数。
7、mybatis一二级缓存。
mybatis一级缓存是SqlSession级别的。SqlSession是mybatis-xxx.jar包中的一个接口,全类名是org.apache.ibatis.session.SqlSession。在操作数据库时需要构造SqlSession对象,查询结果会保存到SqlSession对象中。如果下一次查询还是用的此SqlSession对象,且查询条件一样,则不会去查数据库,而是直接从SqlSession对象中取出数据,并返回。反之,如果每次查询都是用的新的SqlSession对象,或是同一个SqlSession对象但查询条件不一样,或是同一个SqlSession对象但查询之间穿插了增删改,则一级缓存就用不上。增删改操作会清空一级缓存数据。
mybatis二级缓存是多个SqlSession共享的。默认关闭,不建议使用。如果要使用的话,首先需要打开总开关,在mybatis的配置文件中添加
<settings> <!--开启二级缓存--> <setting name="cacheEnabled" value="true"/> </settings>
然后,哪个mapper想用二级缓存,就在哪个mapper下添加<cache />,具体是在<mapper namespace="xxx">下面添加<cache />。
如果二级缓存开启的话,一条查询语句会首先从二级缓存中查找数据,如果二级缓存没有,则去一级缓存中查找数据,如果能拿到的话,就把数据放到二级缓存中,同时返回。如果一级缓存也没有,则会去查库,把查询结果放到一级缓存、二级缓存中,并返回。
8、线上某接口响应慢,用什么工具或者方法定位问题?
9、从kafka的架构设计角度解释一下kafka为什么能够支持高并发?
见
10、spark reduceByKey、groupByKey有什么区别?常用的方法有哪些?
11、spark从kafka拉取数据有哪几种方式?
利用KafkaUtils工具类(org.apache.spark.streaming.kafka.KafkaUtils,在spark-streaming-kafka-xxx.jar包中),有3种方式:
1)createDirectStream()一系列重载方法:
2)createStream()一系列重载方法:
3)createRDD()一系列重载方法:
oppo面试题的更多相关文章
- 2018 oppo校招前端面试题
1.Es6 2.http请求过程 3.js事件执行流程(蒙蔽中) [默认冒泡,由内到外,] 4.css 样式选择器的优先级 (!important在类选择器和id选择器都可以使用,但不推荐使用) 5. ...
- Java面试题(二)--MySQL
1 存储引擎 1.简单描述一个Mysql的内部结构? MySQL的基本架构示意图: 大体来说,MySQL可以分为server层和存储引擎层两部分. ① server层包括连接器.查询缓存.分析器.优化 ...
- .NET面试题系列[8] - 泛型
“可变性是以一种类型安全的方式,将一个对象作为另一个对象来使用.“ - Jon Skeet .NET面试题系列目录 .NET面试题系列[1] - .NET框架基础知识(1) .NET面试题系列[2] ...
- 关于面试题 Array.indexof() 方法的实现及思考
这是我在面试大公司时碰到的一个笔试题,当时自己云里雾里的胡写了一番,回头也曾思考过,最终没实现也就不了了之了. 昨天看到有网友说面试中也碰到过这个问题,我就重新思考了这个问题的实现方法. 对于想进大公 ...
- 对Thoughtworks的有趣笔试题实践
记得2014年在网上看到Thoughtworks的一道笔试题,当时觉得挺有意思,但是没动手去写.这几天又在网上看到了,于是我抽了一点时间写了下,我把程序运行的结果跟网上的答案对了一下,应该是对的,但是 ...
- 从阿里巴巴笔试题看Java加载顺序
一.阿里巴巴笔试题: public class T implements Cloneable { public static int k = 0; public static T t1 = new T ...
- JAVA面试题
在这里我将收录我面试过程中遇到的一些好玩的面试题目 第一个面试题:ABC问题,有三个线程,工作的内容分别是打印出"A""B""C",需要做的 ...
- C++常考面试题汇总
c++面试题 一 用简洁的语言描述 c++ 在 c 语言的基础上开发的一种面向对象编程的语言: 应用广泛: 支持多种编程范式,面向对象编程,泛型编程,和过程化编程:广泛应用于系统开发,引擎开发:支持类 ...
- .NET面试题系列[4] - C# 基础知识(2)
2 类型转换 面试出现频率:主要考察装箱和拆箱.对于有笔试题的场合也可能会考一些基本的类型转换是否合法. 重要程度:10/10 CLR最重要的特性之一就是类型安全性.在运行时,CLR总是知道一个对象是 ...
随机推荐
- spring map获取同类型的bean
今天看博客怎么减少if else 方法, 才发现spring 还有很多功能我没有用到,以后真的得花时间学学spring,今天学到的东西如下: 1.定义一个接口 store public interfa ...
- springboot An incompatible version [1.1.32] of the APR based Apache Tomcat Native library is installed, while Tomcat requires version [1.2.14]
1.错误 An incompatible version [1.1.32] of the APR based Apache Tomcat Native library is installed, wh ...
- assert 与if
strlen的实现用不用加断言(assert)? http://en.cppreference.com/w/cpp/error/assert 自己写strlen实现会加assert判断空指针,Debu ...
- unity不规则按钮解决方案
一种是alpha检测 一种是设置collider 参考: https://zhuanlan.zhihu.com/p/34204396 下面给出第二种方案代码 ///按钮多边形点击方案,注意Canvas ...
- 在Window平台是模拟Linux的Shell环境
在Linux平台模拟Linux的shell环境,可以通过一个软件实现:Cygwin(点击进入官网下载好即可),如下图(选择对应的版本进行下载): 安装: 1. 双击运行下载的安装包(选择从网络安装), ...
- MSF——客户端渗透之VBScript感染
弱点扫描 根据信息收集的结果搜索漏洞利用模块 结合外部漏洞扫描系统对大IP地址段进行批量扫描 误报率.漏报率 VNC密码破解 客户端渗透 VBScript感染方式 利用 宏 感染word.exce ...
- Git-第二篇廖雪峰Git教程学习笔记(1)基本命令,版本回退
1.安装Git-2.16.2-64-bit.exe后,设置用户名,用户邮箱 #--global参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地 ...
- Java对象多态性——对象的转型(引用类型之间的类型转换)
Java引用变量有两个类型:编译时类型和运行时类型.编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定. 若编译时类型和运行时类型不一致,就出现多态 正常的方法调用(本态调用 ...
- linux复杂命令
1,查看包含zypper且不包含ar的进程信息的2,3,8,9列信息 ps -ef|grep zypper|grep -v ar|awk '{print $2,$3,$8,$9}' eg:查看包含zy ...
- Python pass是空语句用法
在条件判断,还是函数中,有时候不需要输出任何东西,也不能留空,python提供空的语句,下面讲述pass空语句的用法 1,关键词 pass 2,用法 for letter in 'Python': i ...