线程池
常用的创建线程池类:ThreadPoolExecutor.
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
corePoolSize:核心线程数量,在没有用的时候,也不会被回收。
maximumPoolSize:最大线程的数量。
keepAliveTime,就是线程池中除了核心线程之外的其他的最长可以保留的时间。
util:就是计算这个时间的一个单位。
workQueue:等待队列,任务可以储存在任务队列中等待被执行,执行的是FIFIO原则(先进先出)。
threadFactory,就是创建线程的线程工厂。
handler,是一种拒绝策略,我们可以在任务满了知乎,拒绝执行某些任务。
线程池的执行流程:任务进来时,首先执行判断,判断核心线程是否处于空闲状态,如果不是,核心线程就先就执行任务,如果核心线程已满,则判断任务队列是否有地方存放该任务,若果有,就将任务保存在任务队列中,等待执行,如果满了,在判断最大可容纳的线程数,如果没有超出这个数量,就开创非核心线程执行任务,如果超出了,就调用handler实现拒绝策略。
graph LR
A(提交任务) --> B{核心线程<br/>是否已满}
B--否-->C(创建核心线程执行任务)
B--是-->D{队列是否已满}
D--否-->E(任务放入队列)
D--是-->F{线程池是否已满<br/>大于maxPollSize}
F--否-->H(创建线程执行任务)
F--是-->G(执行拒绝策略)
classDef default fill:#FFE4E1,stroke:#000000,stroke-width:2px;
handler的拒绝策略:1、AbortPolicy:不执行新任务,直接抛出异常,提示线程池已满
2、第二种DisCardPolicy:不执行新任务,也不抛出异常
3、第三种DisCardOldSetPolicy:将消息队列中的第一个任务替换为当前新进来的任务执行
4、第四种CallerRunsPolicy:直接调用execute来执行当前任务
五,四种常见的线程池:
CachedThreadPool:可缓存的线程池,该线程池中没有核心线程,非核心线程的数量为Integer.max_value,就是无限大,当有需要时创建线程来执行任务,没有需要时回收线程,适用于耗时少,任务量大的情况。
SecudleThreadPool:周期性执行任务的线程池,按照某种特定的计划执行线程中的任务,有核心线程,但也有非核心线程,非核心线程的大小也为无限大。适用于执行周期性的任务。
SingleThreadPool:只有一条线程来执行任务,适用于有顺序的任务的应用场景。
FixedThreadPool:定长的线程池,有核心线程,核心线程的即为最大的线程数量,没有非核心线程、
面试精选:
spring循环依赖处理:www.cnblogs.com/zzq6032010/…
springboot启动流程
classloader双亲委派模型
classloader双亲委派模型,以及为什么要这样设计
简单总结两个优点: 1、因为双亲委派是向上委托加载的,所以它可以确保类只被加载一次,避免重复加载;
2、Java的核心API都是通过引导类加载器进行加载的,如果别人通过定义同样路径的类比如java.lang.Integer,类加载器通过向上委托,两个Integer,那么最终被加载的应该是jdk的Integer类,而并非我们自定义的,这样就避免了我们恶意篡改核心包的风险;
算法类
排序:www.cnblogs.com/ll409546297…
冒泡排序:核心每一个外层选取一个最大值放到最后。
int[] arr = {1, 21, 12, 232, 32};
//冒泡
for (int i = 0; i < arr.length; i++) {
//外层循环,遍历次数
for (int j = 0; j < arr.length - i - 1; j++) {
//内层循环,升序(如果前一个值比后一个值大,则交换)
//内层循环一次,获取一个最大值
if (arr[j] > arr[j + 1]) {
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
合并两个有序链表:blog.csdn.net/fengpojian/…
爬楼梯:blog.csdn.net/qq_35206244…
//当n < 0时,无解,当n = 1 时,f ( n ) = 1, 当n = 2时,有两种方法,一次1级爬2次,或一次2级,
//当 n > 2时,得出递归方程,f(n) = f(n-1) + f(n-2)。
public static int step(int n) {
if (n < 0) return -1;
if (n <= 2) return n;
return step(n - 1) + step(n - 2);
}
环形链表判定:www.cnblogs.com/xiaochuan94…
//使用双指针,一个是正常向前,一次移动一个节点,第二个是间隔一个节点向前移动,如果第二个指针碰到了可以循环
//的节点,会在循环的过程中遇到第一个指针,此时就满足了形成循环的条件。
public boolean hasCycle(ListNode head) {
if (head == null) {
return false;
}
ListNode slow = head;
ListNode fast = head;
while (slow != null && fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
return true;
}
}
return false;
}
mysql索引原理、sql优化、慢查询、jvm、redis等。
synchronized和Lock
首先Java中的ReentrantLock 默认的lock()方法采用的是非公平锁。 synchronized和Lock的原理是什么,有什么区别,是不是重入锁(原理),是不是公平锁,可不可以中断,锁的膨胀; Redis分布式锁的设计; 数据库索引的设计; b树和b+树区别 innodb怎样执行普通索引 事务具有四个特征:原子性( Atomicity )、一致性( Consistency )、隔离性( Isolation )和持续性( Durability )。这四个特性简称为 ACID 特性。
Read uncommitted 读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据。
Read committed 读提交,顾名思义,就是一个事务要等另一个事务提交后才能读取数据。(ORACLE)
Repeatable read重复读,就是在开始读取数据(事务开启)时,不再允许修改操作。(MYSQL)
Serializable 序列化 Serializable 是最高的事务隔离级别,在该级别下,事务串行化顺序执行
Java对象占用分析
类型 | 默认值 | 占用内存(字节) |
| ------- | -------- | -------- |
| boolean | false | 1 |
| byte | (byte)0 | 1 |
| char | '\u0000' | 2 |
| short | (short)0 | 2 |
| int | 0 | 4 |
| long | 0L | 8 |
| float | 0.0f | 4 |
| double | 0.0d | 8
对象引用 4个字节,对象头12个字节