总结
以上是字节二面的一些问题,面完之后其实挺后悔的,没有提前把各个知识点都复习到位。现在重新好好复习手上的面试大全资料(含JAVA、MySQL、算法、Redis、JVM、架构、中间件、RabbitMQ、设计模式、Spring等),现在起闭关修炼半个月,争取早日上岸!!!
下面给大家分享下我的面试大全资料
- 第一份是我的后端JAVA面试大全
后端JAVA面试大全
- 第二份是MySQL+Redis学习笔记+算法+JVM+JAVA核心知识整理
MySQL+Redis学习笔记算法+JVM+JAVA核心知识整理
- 第三份是Spring全家桶资料
MySQL+Redis学习笔记算法+JVM+JAVA核心知识整理
可以看到,使用 submit() 可以执行带有返回值的任务或者无返回值的任务,而 execut() 只能执行不带返回值的任务。
3.2.4 线程工厂
作用:为线程池提供现成的创建。
提供的功能:
-
设置线程池中线程的命名规则;
-
设置线程优先级;
-
设置线程分组;
-
设置线程类型(守护线程 || 用户线程)。
示例代码:
public class ThreadPoolDemo3 {
public static void main(String[] args) {
// 1.创建线程工厂
ThreadFactory factory = r -> {
// 一定要把任务 Runnable 设置给新线程
Thread thread = new Thread(r);
// 设置线程的命名规则
thread.setName("我的线程:" + r.hashCode());
// 设置线程的优先级
thread.setPriority(Thread.MAX_PRIORITY);
return thread;
};
ExecutorService service = Executors.newFixedThreadPool(5, factory);
for (int i = 0; i < 5; i++) {
service.submit(() -> {
// 任务
Thread thread = Thread.currentThread();
System.out.println("线程池开始执行:" + thread.getName() + "线程池优先级:" + thread.getPriority());
});
}
}
}
运行结果:
3.2 带缓存的线程池(Executors.newCachedThreadPool)
线程池会根据任务数创建线程,并且在一定时间内可以重复使用这些线程。
示例代码:
public class ThreadPoolDemo4 {
public static void main(String[] args) {
// 创建线程池
ExecutorService service = Executors.newCachedThreadPool();
for (int i = 0; i < 1000; i++) {
int finalI = i;
service.submit(() -> System.out.println("i:" + finalI + " 线程名称:" + Thread.currentThread().getName()));
}
}
}
运行结果:
该方式适用于短时间有且有大量任务的场景,它的缺点是可能占用很多资源。
3.3 执行定时任务(Executors.newSingleThreadExecutor)
3.3.1 延迟执行(1次)
示例代码:
public class ThreadPoolDemo12 {
public static void main(String[] args) {
ScheduledExecutorService threadPool =
Executors.newScheduledThreadPool(10);
// 定时任务
System.out.println("设置定时任务:" + new Date());
// 延迟 n 秒后执⾏(只执⾏⼀次)
threadPool.schedule(() -> System.out.println("schedule:" + new Date()), 2, TimeUnit.SECONDS);
}
}
执行结果:
延迟 2s 后执行一次。
3.3.2 固定频率执行( scheduleAtFixedRate)
示例代码:
public class ThreadPoolDemo13 {
public static void main(String[] args) {
ScheduledExecutorService threadPool =
Executors.newScheduledThreadPool(10);
// 定时任务
System.out.println("设置定时任务:" + new Date());
threadPool.scheduleAtFixedRate(() ->
System.out.println("scheduleAtFixedRate:" + new Date()), 3, 2, TimeUnit.SECONDS);
}
}
运行结果:
延迟3s后执行,之后每2s执行一次。
参数解释:
-
参数1:执行任务;
-
参数2:延迟 n 秒后执行;
-
参数3:执行定时任务的频率;
-
参数4:配合参数3使用的时间单位。
3.3.3 scheduleAtFixedRate VS scheduleWithFixedDelay
scheduleAtFixedRate 是以上⼀次任务的开始时间,作为下次定时任务的参考时间的(参考时间+延迟任务=任务执行)。
示例代码:
public class ThreadPoolDemo5 {
public static void main(String[] args) {
// 创建线程池
ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
System.out.println("添加任务执行时间:" + LocalDateTime.now());
// 2s之后开始执行定时任务,定时任务每隔4s执行一次
service.scheduleAtFixedRate(() -> {
System.out.println("执行了任务:" + LocalDateTime.now());
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, 2, 4, TimeUnit.SECONDS);
}
}
运行结果:
2s后开始执行定时任务,每隔5s执行一次。
设置的是每隔4秒执行一次定时任务,为什么实际上是5s执行一次呢?
注意,如果执行任务时间大于设置的定时任务执行时间,那么此方法会以执行任务的时间为准,简而言之,就是哪个时间长就以哪个时间作为定时任务执行的周期。
scheduleWithFixedDelay 是以上⼀次任务的结束时间,作为下次定时任务的参考时间的。
示例代码:
public class ThreadPoolDemo5 {
public static void main(String[] args) {
// 创建线程池
ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
System.out.println("添加任务执行时间:" + LocalDateTime.now());
// 2s之后开始执行定时任务,每次执行间隔4秒
service.scheduleWithFixedDelay(() -> {
System.out.println("执行了任务:" + LocalDateTime.now());
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, 2, 4, TimeUnit.SECONDS);
}
}
运行结果:
2s后开始执行任务,每隔9秒执行一次定时任务。
为什么这个也不是每隔4s执行一次,而是9s呢???
因为 scheduleWithFixedDelay 是以上⼀次任务的结束时间,作为下次定时任务的参考时间的,上个任务执行5s后,再延时4s执行延时任务。
3.4 定时任务单线程(Executors.newSingleThreadScheduledExecutor)
示例代码:
public class ThreadPoolDemo6 {
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
System.out.println("添加任务时间:" + LocalDateTime.now());
service.schedule(() -> System.out.println("执行任务:" + LocalDateTime.now()), 2, TimeUnit.SECONDS);
}
}
运行结果:
3.5 单线程线程池(Executors.newSingleThreadExecutor)
示例代码:
public class ThreadPoolDemo7 {
public static void main(String[] args) {
ExecutorService service = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
int finalI = i;
service.submit(() -> System.out.println("任务:" + finalI + ", 线程名:" + Thread.currentThread().getName()));
}
}
}
运行结果:
单线程的线程池有什么意义呢?
-
自定义拒绝策略;
-
提供了任务队列和任务管理的功能。
3.6 根据当前CPU生成线程池(Executors.newWorkStealingPool)
示例代码:
public class ThreadPoolDemo8 {
public static void main(String[] args) {
ExecutorService service = Executors.newWorkStealingPool();
for (int i = 0; i < 100; i++) {
service.submit(() -> System.out.println("线程名:" + Thread.currentThread().getName()));
}
while (!service.isTerminated()){
}
}
}
运行结果:
3.7 手动方式(ThreadPoolExecutor)
3.7.1 创建忽略最新任务的线程池
示例代码:
public class ThreadPoolDemo11 {
public static void main(String[] args) {
ThreadFactory factory = r -> {
Thread thread = new Thread(r);
return thread;
};
// 手动方式创建线程池
ThreadPoolExecutor executor =
new ThreadPoolExecutor(2, 2, 10, TimeUnit.SECONDS,
new LinkedBlockingDeque<>(2), factory, new ThreadPoolExecutor.DiscardPolicy());
for (int i = 0; i < 5; i++) {
int finalI = i;
executor.submit(() -> {
try {
Thread.sleep(finalI * 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "执行任务" + finalI);
});
}
// 终止线程池
executor.shutdown();
}
}
运行结果:
3.7.2 ThreadPoolExecutor 参数说明
-
corePoolSize:核心线程数,可以大致理解为长期驻留的线程数目(除非设置了allowCoreThreadTimeOut)。对于不同的线程池,这个值可能会有很大区别,比如newFixedThreadPool 会将其设置为 nThreads,而对于 newCachedThreadPool 则是为 0。
-
maximumPoolSize:顾名思义,就是线程不够时能够创建的最⼤线程数。同样进⾏对比,对于newFixedThreadPool,当然就是 nThreads,因为其要求是固定大小,而 newCachedThreadPool 则是 Integer.MAX_VALUE。
-
keepAliveTime:空闲线程的保活时间,如果线程的空闲时间超过这个值,那么将会被关闭。注意此值生效条件必须满足:空闲时间超过这个值,并且线程池中的线程数少于等于核⼼线程数corePoolSize。当然核心线程默认是不会关闭的,除非设置了allowCoreThreadTimeOut(true)那么核心线程也可以被回收。
-
TimeUnit:时间单位。
-
BlockingQueue:任务队列,用于存储线程池的待执行任务的。
-
threadFactory:⽤于生成线程,⼀般我们可以⽤默认的就可以了。
-
handler:当线程池已经满了,但是又有新的任务提交的时候,该采取什么策略由这个来指定。有几种方式可供选择,像抛出异常、直接拒绝然后返回等,也可以自己实现相应的接口实现自己的逻辑。
3.7.3 线程池执行流程
3.7.4 拒绝策略(5种(4(JDK提供的) + 1(自定义拒绝策略)))
JDK提供的四种拒绝策略:
-
DiscardPolicy : 忽略旧任务(队列第一个任务)
-
AbortPolicy : 提示异常,拒绝执行(默认的拒绝策略)
-
CallerRunsPolicy : 使用调用线程池的线程来执行任务
-
DiscardOldestPolicy : 忽略最新任务
自定义拒绝策略:
示例代码:
public class ThreadPoolDemo10 {
public static void main(String[] args) {
ThreadFactory factory = r -> {
Thread thread = new Thread(r);
return thread;
};
// 手动方式创建线程池
ThreadPoolExecutor executor =
new ThreadPoolExecutor(2, 2, 10, TimeUnit.SECONDS,
new LinkedBlockingDeque<>(2), factory,
new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
// 自定义拒绝策略
System.out.println("自定义拒绝策略");
}
});
for (int i = 0; i < 5; i++) {
int finalI = i;
executor.submit(() -> {
try {
Thread.sleep(finalI * 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "执行任务" + finalI);
});
}
// 终止线程池
executor.shutdown();
}
}
运行结果:
4. 线程池状态
=========
独家面经总结,超级精彩
本人面试腾讯,阿里,百度等企业总结下来的面试经历,都是真实的,分享给大家!
Java面试准备
准确的说这里又分为两部分:
- Java刷题
- 算法刷题
Java刷题:此份文档详细记录了千道面试题与详解;
}
}
**运行结果:**
![595f02605134493bb8277ddb1d3642a2.png](https://img-blog.csdnimg.cn/595f02605134493bb8277ddb1d3642a2.png)
4\. 线程池状态
=========
# 独家面经总结,超级精彩
本人面试腾讯,阿里,百度等企业总结下来的面试经历,都是真实的,分享给大家!
[外链图片转存中...(img-FyFzGSAm-1715377457868)]
[外链图片转存中...(img-LtIgdRNY-1715377457868)]
[外链图片转存中...(img-OZd6Q2PJ-1715377457869)]
[外链图片转存中...(img-PEXfHSao-1715377457870)]
# Java面试准备
准确的说这里又分为两部分:
1. Java刷题
2. 算法刷题
Java刷题:此份文档详细记录了千道面试题与详解;
[外链图片转存中...(img-AUTSxK2q-1715377457870)]
[外链图片转存中...(img-etZtCzwi-1715377457870)]
> **本文已被[CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)收录**
**[需要这份系统化的资料的朋友,可以点击这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**