1. 如果创建一个线程池,有哪些参数需要设置。
核心线程数,最大线程数,空闲线程存活时间,时间单位,工作队列,拒绝任务处理器。
2. 如果有5个线程分别处理不同的任务,需要等这5个线程都执行完成后输出一条日志,如何解决。
- Java并发编程:CountDownLatch、CyclicBarrier和 Semaphore:http://www.importnew.com/21889.html
- CountDownLatch的简单理解(原理是AQS): https://blog.csdn.net/joenqc/article/details/76794356
3. 分布式事务,批处理。
2PC,TCC
4. 并发包中有哪些内容?你比较熟悉哪些内容,并详细讲解下。
我们常说的并发工具包就是java.util.concurrent及其子包,集中了Java并发的各种基础工具类,其中主要包括以下几个方面:
- 提供了比synchronized更加高级的各种同步结构,包括CountDownLatch、CyclicBarrier、Semaphore等,可以实现更加丰富的多线程操作,比如利用semaphore作为资源控制器,限制同时进行工作的线程数量;
- 各种线程安全的容器,比如最常见的ConcurrentHashMap、有序的ConcurrentSkipListMap,或者通过类似快照机制,实现线程安全的动态数组CopyOnWriteArrayList等;
- 各种并发队列实现,如各种BlockingQueue实现,比较典型的ArrayBlockingQueue、SynchorousQueue或针对特定场景的PriorityBlockingQueue等;
- 强大的Executor框架,可以创建各种不同类型的线程池,调度任务运行等,绝大部分情况下,不再需要自己从头实现线程池和任务调度器。
5. JVM的垃圾回收机制?有哪些算法?调用了什么方法?
https://www.cnblogs.com/aspirant/p/8662690.html
6. 内存映像分析工具
jmap -dump 生成dump文件, MAT(Memory Analyzer Tool)工具分析dump文件
7. 数据库的锁
- 乐观锁:乐观的任务数据不会被改,需要自己实现,每次查的时候获取版本,update时候比较版本(时间戳);
- 悲观锁:数据库默认锁,认为数据被改动,包括共享锁(lock in share mode),排它锁(for update)
https://blog.csdn.net/puhaiyang/article/details/72284702
8. 什么是CAS和AQS?
https://blog.csdn.net/u010862794/article/details/72892300
9. 分布式锁
CAP定理:一个分布式系统不可能同时满足一致性(C),可用性(A)和分区容错性(P)这三个基本需求,最多只能同时满足其中的两项。
三种实现方式:
- 基于数据库实现分布式锁; 共享锁,排他锁
- 基于缓存(Redis等)实现分布式锁;
- 基于Zookeeper实现分布式锁;
https://blog.csdn.net/xlgen157387/article/details/79036337
10. LinkedHashMap分析
https://www.jianshu.com/p/8724a055289b
11. LRU Cache原理和实现
https://blog.csdn.net/caoshangpa/article/details/78783749
12. 谈谈对IOC和AOP的理解
IOC控制反转是相对我们之前创建对象都是new的方式来讲的,而现在我们将对象的管理交给spring,由spring去控制,降低了对象与对象之间的耦合度。
AOP是面向切面编程,面向对象编程引入封装、继承、多态等概念建立一种纵向的开发方式,而AOP则是建立了一种横向的开发方式。对于如权限认证、日志、事务等几乎业务功能都需要的功能,若采用OOP的设计则会产生大量的重复代码,不利于各模块的重用。
而AOP则把系统分为两部分:核心关注点和横切关注点。业务的核心处理流程为核心关注点,而权限认证、日志、事务等则为横切关注点。AOP思想的作用在于分离系统中的各种关注点,进一步解耦模块间的相互依赖,提高模块的重用性。
13. IOC有什么好处
- 将bean交给Spring容器管理,开发不用关心具体细节。
- spring容器中的bean都是单例的
14. 代理模式
-
静态代理:
1)首先创建一个接口(JDK代理都是面向接口的);
2)然后创建具体实现类来实现这个接口;
3)再创建一个代理类同样实现这个接口,不同之处在于,具体实现类的方法中需要将接口中定义的方法的业务逻辑功能实现,而代理类中持有具体实现类的引用,代理类的方法中使用该引用调用对应方法。
这样我们在需要使用接口中的某个方法的功能时直接调用代理类的方法即可,将具体的实现类隐藏在底层。 -
动态代理
只能对实现了接口的类生产代理,不能针对类。1)首先创建一个接口(JDK代理都是面向接口的);
2)然后创建具体实现类来实现这个接口;
3)创建代理对象,实现java.lang.reflect.InvocationHandler接口,实现接口方法。在代理对象传入被代理对象实例。
https://blog.csdn.net/jinjin603/article/details/78951755
15. maven构建生命周期
1:clean、2:resources、3:compile、4:testResources、5:testCompile、6:test、7:jar、8:install
https://blog.csdn.net/zhaojianting/article/details/80321488
16. 数据库索引类型
-
普通索引
-
唯一索引:索引的值必须唯一,允许为空
-
全文索引
-
单列索引和多列索引
-
组合索引(最左前缀)
ALTER TABLE article ADD INDEX index_titme_time (title(50),time(10))
建立这样的组合索引,其实是相当于分别建立了下面两组组合索引:
–title,time
–title为什么没有time这样的组合索引呢?这是因为MySQL组合索引“最左前缀”的结果。简单的理解就是只从最左面的开始组合。并不是只要包含这两列的查询都会用到该组合索引。
–使用到上面的索引 SELECT * FROM article WHREE title='测试' AND time=1234567890; SELECT * FROM article WHREE utitle='测试'; –不使用上面的索引 SELECT * FROM article WHREE time=1234567890;
17. 聚集索引和非聚集索引
聚集索引:数据行的物理顺序与列值(一般是主键的那一列)的逻辑顺序相同,一个表中只能拥有一个聚集索引。例如新华字典拼音目录从A到Z。
非聚集索引:该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以拥有多个非聚集索引。例如新华字典可以根据偏旁部首来查询。
18. Java线程的5种状态及状态之间转换
https://blog.csdn.net/u013129944/article/details/73741161
19. 分布式事务1
https://www.cnblogs.com/savorboard/p/distributed-system-transaction-consistency.html
20. 分布式事务2
https://www.jianshu.com/p/16b1baf015e8
21. 负载均衡 : https://www.cnblogs.com/microtiger/p/7623858.html
Nginx的特点是:
1、工作在网络的7层之上,可以针对http应用做一些分流的策略,比如针对域名、目录结构;
2、Nginx对网络的依赖比较小;
3、Nginx安装和配置比较简单,测试起来比较方便;
4、也可以承担高的负载压力且稳定,一般能支撑超过1万次的并发;
5、Nginx可以通过端口检测到服务器内部的故障,
比如根据服务器处理网页返回的状态码、超时等等,
并且会把返回错误的请求重新提交到另一个节点,不过其中缺点就是不支持url来检测;
6、Nginx对请求的异步处理可以帮助节点服务器减轻负载;
7、Nginx能支持http和Email,这样就在适用范围上面小很多;
8、不支持Session的保持、对Big request header的支持不是很好,
另外默认的只有Round-robin和IP-hash两种负载均衡算法。
22. 分布式算法(一致性Hash算法)
https://www.cnblogs.com/moonandstar08/p/5405991.html
23. SpringBoot的优缺点
- 优点:
- springboot内嵌了servlet容器。
- 快速整合第三方框架,无需配置文件。
- 配合各种starter使用,基本上可以做到自动化配置,提高了开发效率。
- 配合Maven或Gradle等构件工具,打包、部署简单。
- 缺点:
- 没有相应的服务发现和注册。
24. IO和NIO的区别
IO | NIO |
---|---|
面向流 | 面向缓冲 |
阻塞IO | 非阻塞IO |
无 | 选择器 |
-
面向流与面向缓冲
Java NIO和IO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。 Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它缓存到一个缓冲区。 Java NIO的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是,还需要检查是否该缓冲区中包含所有您需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。 -
阻塞与非阻塞IO
Java IO的各种流是阻塞的。这意味着,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。 Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。 线程通常将非阻塞IO的空闲时间用于在其它通道上执行IO操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)。 -
选择器(Selectors)
Java NIO的选择器允许一个单独的线程来监视多个输入通道,你可以注册多个通道使用一个选择器,然后使用一个单独的线程来“选择”通道:这些通道里已经有可以处理的输入,或者选择已准备写入的通道。这种选择机制,使得一个单独的线程很容易来管理多个通道。
https://www.cnblogs.com/aspirant/p/8630283.html
25. OSI七层协议
26. synchronized和Lock的区别
类别 | synchronized | Lock |
---|---|---|
存在层次 | java关键字,在jvm层 | 类 |
锁的释放 | 1.获取锁的线程执行完了该代码块,然后线程释放对锁的占有;2. 线程执行发生异常,此时JVM会让线程自动释放锁。 | Lock则必须要在finally中手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象。 |
锁的获取 | 假设A线程获得锁,B线程等待,如果A阻塞,B线程一直会等待。 | 多种方式 |
锁的状态 | 无法判断 | 可以判断 |
锁类型 | 可重入,不可中断,非公平 | 可重入,可判断,可公平 |
性能 | 少量同步 | 大量同步 |
Lock获取锁的方式:
//获取锁,如果锁被暂用则一直等待
void lock();
//用该锁的获得方式,如果线程在获取锁的阶段进入了等待,那么可以中断此线程,先去做别的事
void lockInterruptibly() throws InterruptedException;
//注意返回类型是boolean,如果获取锁的时候锁被占用就返回false,否则返回true
boolean tryLock();
//比起tryLock()就是给了一个时间期限,保证等待参数时间
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;