京东总部的位置有点捉急,周围荒芜人烟,位于一片农田之中,2016年末,刘强东开始将京东定义为一个技术型驱动的公司,开始打造众多的技术团队,技术氛围不错,但是面试官有些木讷。。。
面试题目
1. 多线程:executor原理 线程池 全解
Executor,Executors,ExecutorService,CompletionService,Future,Callable
- Executors类,提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService接口。
-
public static ExecutorService newFixedThreadPool(int nThreads)
创建固定数目线程的线程池。 -
public static ExecutorService newCachedThreadPool()
创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。 -
public static ExecutorService newSingleThreadExecutor()
创建一个单线程化的Executor。 -
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。
-
ExecutorService
与生命周期
-
ExecutorService
扩展了Executor
并添加了一些生命周期管理的方法。 - 一个
Executor
的生命周期有三种状态,运行 ,关闭 ,终止 。Executor
创建时处于运行状态。当调用ExecutorService.shutdown()
后,处于关闭状态,isShutdown()
方法返回true
。这时,不应该再想Executor
中添加任务,所有已添加的任务执行完毕后,Executor
处于终止状态,isTerminated()
返回true
。 - 如果
Executor
处于关闭状态,往Executor
提交任务会抛出unchecked exception RejectedExecutionException
。
- 使用
Callable
,Future
返回结果
-
Future<V>
代表一个异步执行的操作,通过get()
方法可以获得操作的结果,如果异步操作还没有完成,则,get()
会使当前线程阻塞。FutureTask<V>
实现了Future<V>
和Runable<V>
。Callable
代表一个有返回值得操作。
-
CompletionService
在刚在的例子中,getResult()方法的实现过程中,迭代了FutureTask的数组,如果任务还没有完成则当前线程会阻塞,如果我们希望任意字任务完成后就把其结果加到result中,而不用依次等待每个任务完成,可以使CompletionService。生产者submit()执行的任务。使用者take()已完成的任务,并按照完成这些任务的顺序处理它们的结果 。也就是调用CompletionService的take方法是,会返回按完成顺序放回任务的结果,CompletionService内部维护了一个阻塞队列BlockingQueue,如果没有任务完成,take()方法也会阻塞。修改刚才的例子使用CompletionService:
2. hashmap实现原理,hashtable和hashmap区别,为什么hashmap效率高不安全,concurrenthashmap 为什么线程安全,怎样实现的.
在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。
HashMap底层就是一个数组结构,数组中的每一项又是一个链表。当新建一个HashMap的时候,就会初始化一个数组。
详细介绍:
hashmap原理全解
hashtable原理全解
3. 手写单例模式示例,单链表倒序排列
单例模式的几种写法:详解点击:单例模式的七种写法
//写法一:懒加载,线程不安全
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
//写法二:懒加载,线程安全
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
//写法三:不能懒加载
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
//写发四:写法三的变种
public class Singleton {
private Singleton instance = null;
static {
instance = new Singleton();
}
private Singleton (){}
public static Singleton getInstance() {
return this.instance;
}
}
//写法五:静态内部类
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
//写法六:双重校验
public class Singleton {
private volatile static Singleton singleton; //保证变量值统一
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
单链表倒序排列
/**
* java 实现单链表的逆序
* @author Administrator
*
*/
public class SingleLinkedReverse {
//定义单链表,每个节点包含数据和下一个节点的地址
class Node {
int data;
Node next;
public Node(int data) {
this.data = data;
}
}
public static void main(String[] args) {
SingleLinkedReverse slr = new SingleLinkedReverse();
//定义两个链表
Node head, tail;
//新建一个链表头结点
head = tail = slr.new Node(0);
//新建一个长度为10的链表tail
for (int i = 1; i < 10; i++) {
Node p = slr.new Node(i);
tail.next = p;
tail = p;
}
//tail返回到头节点0 此时head在头结点
tail = head;
//循环链表
while (tail != null) {
System.out.print(tail.data + " ");
tail = tail.next;
}
head = reverse(head);
while (head != null) {
System.out.print(head.data + " ");
head = head.next;
}
}
/* 核心算法
前后交换位置
*/
private static Node reverse(Node head) {
Node p1, p2 = null;
p1 = head;
while (head.next != null) {
p2 = head.next;
head.next = p2.next;
p2.next = p1;
p1 = p2;
}
return p2;
}
}
4. 接口和抽象类区别,特点 答案全解
- 抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。
- 抽象类要被子类继承,接口要被类实现。
- 接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现
- 接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
- 抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。
- 抽象方法只能申明,不能实现,接口是设计的结果 ,抽象类是重构的结果
- 抽象类里可以没有抽象方法
- 如果一个类里有抽象方法,那么这个类只能是抽象类
- 抽象方法要被实现,所以不能是静态的,也不能是私有的。
- 接口可继承接口,并可多继承接口,但类只能单根继承。
5. static 特点 执行顺序
父类的 static 语句和 static 成员变量
子类的 static 语句和 static 成员变量
父类的 非 static 语句块和 非 static 成员变量
父类的构造方法
子类的 非 static 语句块和 非 static 成员变量
子类的构造方法
6. sql的执行顺序
SQL Select语句完整的执行顺序:
- from子句组装来自不同数据源的数据;
- where子句基于指定的条件对记录行进行筛选;
- group by子句将数据划分为多个分组;
- 使用聚集函数进行计算;
- 使用having子句筛选分组;
- 计算所有的表达式;
- 使用order by对结果集进行排序。
- select 集合输出。
7. having
在 SQL 中增加 HAVING 子句原因是,WHERE 关键字无法与合计函数一起使用。
SELECT Customer,SUM(OrderPrice) FROM Orders
WHERE Customer='Bush' OR Customer='Adams'
GROUP BY Customer
HAVING SUM(OrderPrice)>1500
8. innodb myisam的区别 和原理 答案全解
两种类型最主要的差别就是Innodb 支持事务处理与外键和行级锁。而MyISAM不支持.所以MyISAM往往就容易被人认为只适合在小项目中使用。
作为使用MySQL的用户角度出发,Innodb和MyISAM都是比较喜欢的,如果数据库平台要达到需求:99.9%的稳定性,方便的扩展性和高可用性来说的话,MyISAM绝对是首选。
9. arraylist linkedlist区别
- 大概的区别
- ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
- 对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
- 对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
- ArrayList和LinkedList在性能上各有优缺点,都有各自所适用的地方,总的说来可以描述如下:
对ArrayList和LinkedList而言,在列表末尾增加一个元素所花的开销都是固定的。对ArrayList而言,主要是在内部数组中增加一项,指向所添加的元素,偶尔可能会导致对数组重新进行分配;而对LinkedList而言,这个开销是统一的,分配一个内部Entry对象。
在ArrayList的中间插入或删除一个元素意味着这个列表中剩余的元素都会被移动;而在LinkedList的中间插入或删除一个元素的开销是固定的。
LinkedList不支持高效的随机元素访问。
ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间
可以这样说:当操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用ArrayList会提供比较好的性能;当你的操作是在一列数据的前面或中间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用LinkedList了
10. 基本请求类型
HTTP协议中共定义了八种方法或者叫“动作”来表明对Request-URI指定的资源的 不同操作方式,具体介绍如下:
OPTIONS:返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送'*'的请求来测试服务器的功能性。
HEAD:向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息。
GET:向特定的资源发出请求。
POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的创建和/或已有资源的修改。
PUT:向指定资源位置上传其最新内容。
DELETE:请求服务器删除Request-URI所标识的资源。
TRACE:回显服务器收到的请求,主要用于测试或诊断。
CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
11. 响应状态码
全解
301和302的区别
- 302重定向是暂时的重定向,搜索引擎会抓取新的内容而保留旧的网址。因为服务器返回302代码,搜索引擎认为新的网址只是暂时的。 SEO 302好于301,但容易被劫持。
- 301重定向是永久的重定向,搜索引擎在抓取新内容的同时也将旧的网址替换为重定向之后的网址。不会发生url劫持
12. 微服务什么概念
微服务是一项在云中部署应用和服务的新技术。大部分围绕微服务的争论都集中在容器或其他技术是否能很好的实施微服务,而红帽说API应该是重点。
WiKi