最后
分享一套我整理的面试干货,这份文档结合了我多年的面试官经验,站在面试官的角度来告诉你,面试官提的那些问题他最想听到你给他的回答是什么,分享出来帮助那些对前途感到迷茫的朋友。
面试经验技巧篇
- 经验技巧1 如何巧妙地回答面试官的问题
- 经验技巧2 如何回答技术性的问题
- 经验技巧3 如何回答非技术性问题
- 经验技巧4 如何回答快速估算类问题
- 经验技巧5 如何回答算法设计问题
- 经验技巧6 如何回答系统设计题
- 经验技巧7 如何解决求职中的时间冲突问题
- 经验技巧8 如果面试问题曾经遇见过,是否要告知面试官
- 经验技巧9 在被企业拒绝后是否可以再申请
- 经验技巧10 如何应对自己不会回答的问题
- 经验技巧11 如何应对面试官的“激将法”语言
- 经验技巧12 如何处理与面试官持不同观点这个问题
- 经验技巧13 什么是职场暗语
面试真题篇
- 真题详解1 某知名互联网下载服务提供商软件工程师笔试题
- 真题详解2 某知名社交平台软件工程师笔试题
- 真题详解3 某知名安全软件服务提供商软件工程师笔试题
- 真题详解4 某知名互联网金融企业软件工程师笔试题
- 真题详解5 某知名搜索引擎提供商软件工程师笔试题
- 真题详解6 某初创公司软件工程师笔试题
- 真题详解7 某知名游戏软件开发公司软件工程师笔试题
- 真题详解8 某知名电子商务公司软件工程师笔试题
- 真题详解9 某顶级生活消费类网站软件工程师笔试题
- 真题详解10 某知名门户网站软件工程师笔试题
- 真题详解11 某知名互联网金融企业软件工程师笔试题
- 真题详解12 国内某知名网络设备提供商软件工程师笔试题
- 真题详解13 国内某顶级手机制造商软件工程师笔试题
- 真题详解14 某顶级大数据综合服务提供商软件工程师笔试题
- 真题详解15 某著名社交类上市公司软件工程师笔试题
- 真题详解16 某知名互联网公司软件工程师笔试题
- 真题详解17 某知名网络安全公司校园招聘技术类笔试题
- 真题详解18 某知名互联网游戏公司校园招聘运维开发岗笔试题
资料整理不易,点个关注再走吧
1 /**
2 * @description: 多线程实现方法2:实现Runnable接口
3 **/
4 @Slf4j
5 public class MyThread2 implements Runnable {
6
7 @Override
8 public void run() {
9 log.info(“MyThread1”);
10 log.info(“MyThread2”);
11 }
12
13 public static void main(String[] args) {
14 MyThread2 m = new MyThread2();
15 //1.调用run方法
16 Thread t1 = new Thread(m);
17 Thread t2 = new Thread(m);
18 t1.start();
19 t2.start();
20 }
21 }
2.3实现 Callable 接口,通过 Future Task 包装器来创建 Thread 线程
可以获取线程的返回值
1 /**
2 * @description: 多线程实现方法2:实现Callable接口
3 * @author: DZ
4 **/
5 @Slf4j
6 public class MyThread3 implements Callable {
7 @Override
8 public String call() throws Exception {
9 log.info(“MyThread1”);
10 log.info(“MyThread2”);
11 return “MyThread3”;
12 }
13
14 public static void main(String[] args) throws ExecutionException, InterruptedException {
15 MyThread3 m = new MyThread3();
16 //存储返回值,其中泛型为返回值的类型
17 FutureTask futureTask = new FutureTask<>(m);
18 new Thread(futureTask).start();
19 System.out.println(futureTask.get());
20 }
21
22 }
2.4通过线程池
2.4.1 线程池的主要参数
1 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue) {
2 this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
3 Executors.defaultThreadFactory(), defaultHandler);
4 }
- corePoolSize
当向线程池提交一个任务时,若线程池已创建的线程数小于corePoolSize,即便此时存在空闲线程,也会通过创建一个新线程来执行该任务,直到已创建的线程数大于或等于corePoolSize时,(除了利用提交新任务来创建和启动线程(按需构造),也可以通过 prestartCoreThread() 或 prestartAllCoreThreads() 方法来提前启动线程池中的基本线程。)
- maximumPoolSize
线程池所允许的最大线程个数。当队列满了,且已创建的线程数小于maximumPoolSize,则线程池会创建新的线程来执行任务。另外,对于无界队列,可忽略该参数
- keepAliveTime
当线程池中线程数大于核心线程数时,线程的空闲时间如果超过线程存活时间,那么这个线程就会被销毁,直到线程池中的线程数小于等于核心线程数
- workQueue
用于传输和保存等待执行任务的阻塞队列
-
ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列
-
LinkedBlockingQueue 一个由链表结构组成的有界阻塞队列
-
PriorityBlockingQueue 一个支持优先级排序的无界阻塞队列
-
DelayQueue 一个使用优先级队列实现的无界阻塞队列
-
SynchronousQueue 一个不存储元素的阻塞队列
-
LinkedTransferQueue 一个由链表结构组成的无界阻塞队列
-
LinkedBlockingDeque 一个由链表结构组成的双向阻塞队列
**作用:**阻塞队列可以保证任务队列中没有任务时阻塞获取任务的线程,使得线程进入wait状态,释放cpu资源。当队列中有任务时才唤醒对应线程从队列中取出消息进行执行。使得在线程不至于一直占用cpu资源。
- threadFactory
用于创建新线程。threadFactory创建的线程也是采用new Thread()方式,threadFactory创建的线程名都具有统一的风格:pool-m-thread-n(m为线程池的编号,n为线程池内的线程编号)
- handler
当线程池和队列都满了,再加入线程会执行此策略
AbortPolicy: 直接抛出异常,阻止线程正常运行
1 public static class AbortPolicy implements RejectedExecutionHandler {
2 public AbortPolicy() {}
3 public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
4 throw new RejectedExecutionException(“Task " + r.toString() +” rejected from " + e.toString());
5 }
6 }
CallerRunsPolicy: 直接在方法的调用线程中执行,除非线程池已关闭
1 public static class CallerRunsPolicy implements RejectedExecutionHandler {
2 public CallerRunsPolicy() {}
3 public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
4 if (!e.isShutdown()) {
5 r.run();
6 }
7 }
8 }
DiscardPolica: 丢弃当前的线程任务而不做任何处理。如果系统允许在资源不足的情况下弃部分任务,则这将是保障系统安全、稳定的一种很好的方案
1 public static class DiscardPolicy implements RejectedExecutionHandler {
2 public DiscardPolicy() {}
3 public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
4 }
5 }
DiscardOlderPolicy: 移除线程队列中最早(老)的一个线程任务,并尝试提交当前任务
1 public static class DiscardOldestPolicy implements RejectedExecutionHandler {
2 public DiscardOldestPolicy() { }
3 public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
4 if (!e.isShutdown()) {
5 e.getQueue().poll();// 最早(老)的任务出队列
6 e.execute®;
7 }
8 }
9 }
2.4.2如何设置线程池
- CPU密集型
尽量使用较小的线程池,一般为CPU核心数+1。 因为CPU密集型任务使得CPU使用率很高,若开过多的线程数,会造成CPU过度切换。
- IO密集型任务
可以使用稍大的线程池,一般为2*CPU核心数。 IO密集型任务CPU使用率并不高,因此可以让CPU在等待IO的时候有其他线程去处理别的任务,充分利用CPU时间
- 混合型任务
线程数 = CPU核心数 * (1+平均等待时间 / 平均工作时间)
2.4.3 代码示例
1 import lombok.extern.slf4j.Slf4j;
2 import org.junit.Test;
3
4 import java.util.concurrent.*;
5
6 /**
7 * @description: 通过线程池实现多线程
8 * @author: DZ
9 **/
10 @Slf4j
11 public class MyThread4 {
12 //通常使用方式,定义前5个参数即可,其余默认
13 private ThreadPoolExecutor threadPoolExecutor0 = new ThreadPoolExecutor(5, 10, 60,
14 TimeUnit.SECONDS, new LinkedBlockingQueue(10));
15
16 //所有参数均自定义(增加工厂ThreadFactory和拒绝方式Handle)
17 private ThreadPoolExecutor threadPoolExecutor1 = new ThreadPoolExecutor(5, 10, 60,
18 TimeUnit.SECONDS, new LinkedBlockingQueue(10), new ThreadFactory() {
19 @Override
20 public Thread newThread(Runnable r) {
21 Thread thread = new Thread®;
22 log.info(“我是线程{}”, thread.getName());
23 return thread;
24 }
25 }, new RejectedExecutionHandler() {
26 @Override
27 public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
28 log.info(“线程被去掉{}”, new Thread®.getName());
29 }
30 });
31
32 //所有参数均自定义,拒绝方式使用默认new ThreadPoolExecutor.AbortPolicy(),new ThreadPoolExecutor.DiscardOldestPolicy(),new ThreadPoolExecutor.CallerRunsPolicy(),new ThreadPoolExecutor.DiscardPolicy()
33 private ThreadPoolExecutor threadPoolExecutor2 = new ThreadPoolExecutor(5, 10, 60,
34 TimeUnit.SECONDS, new LinkedBlockingQueue(10), new ThreadFactory() {
35 @Override
36 public Thread newThread(Runnable r) {
37 Thread thread = new Thread®;
38 log.info(“我是线程{}”, thread.getName());
39 return thread;
40 }
41 }, new ThreadPoolExecutor.DiscardPolicy());
42
43 @Test
44 public void testRunnable() {
45 threadPoolExecutor0.execute(new Runnable() {
46 @Override
47 public void run() {
48 log.info(“MyThread1”);
49 log.info(“MyThread2”);
50 }
51 });
52 }
53
54 @Test
55 public void testCallable() throws ExecutionException, InterruptedException {
56 Future submit = threadPoolExecutor1.submit(new Callable() {
57 @Override
58 public String call() throws Exception {
59 log.info(“MyThread1”);
60 log.info(“MyThread2”);
61 return “MyThread4”;
62 }
63 });
64 System.out.println(submit.get());
65 }
66 }
3 常见的线程池
========
3.1 FixedThreadPool
适用于任务数量已知,且相对耗时的任务
1 public static ExecutorService newFixedThreadPool(int nThreads) {
2 return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());
3 }
3.2 SingleThreadExecutor
这种线程池非常适合所有任务都需要按被提交的顺序来执行的场景,是个单线程的串行。
1 public static ExecutorService newSingleThreadExecutor() {
2 return new FinalizableDelegatedExecutorService
3 (new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue()));
4 }
5
6 public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
7 return new FinalizableDelegatedExecutorService
8 (new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue(),threadFactory));
9 }
3.3 CachedThreadPool
核心线程池为0,存活时间为60s,适合小而快的任务
最后
Service
8 (new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue(),threadFactory));
9 }
3.3 CachedThreadPool
核心线程池为0,存活时间为60s,适合小而快的任务
最后
[外链图片转存中…(img-AdagCK6y-1715377374530)]
[外链图片转存中…(img-ztemel0i-1715377374531)]
[外链图片转存中…(img-BUaqvcep-1715377374532)]