最近的面试题,阿芬有点诧异,因为从之前的基础面试题,到后来的一些涉及分布式、微服务的面试题,再到现在线程池的一些面试题,反正不同的面试官方向不一样,可能现在的面试官想测试你的各种能力,最近有读者给阿粉反馈说面试官从跟帖开始,有点尴尬,还好我加入了没有任何风险的工作。看看面试官问了什么?能谈谈您对进程和线程概念的理解吗?这道题有点基础,但一定是未来的开胃菜。进程与线程的关系进程是应用程序在内存中分配的空间,也就是运行的程序,各个进程之间互不干扰。同时,进程保存程序每时每刻运行的状态。让一个线程执行一个子任务,这样一个进程包含多个线程,每个线程负责一个单独的子任务。进程是一个独立的运行环境,线程是在进程中执行的任务。两者的本质区别在于是否分别占用内存地址空间和其他系统资源(如I/O)。一般来说,线程是属于进程的任务,应该算是一种包含关系。进程是操作系统分配资源的基本单位,线程是操作系统调度的基本单位。多进程也可以实现并发,为什么要用多线程呢?这个问题很有趣。如果你对它了解不多,这个问题真的很难回答。多进程的方式确实可以实现并发,但是多线程的使用要比多进程好。1、进程之间的通信比较复杂,而线程之间的通信比较简单。通常,我们需要使用共享资源,这样更容易在线程之间进行通信。2、进程是重量级的,而线程是轻量级的,所以多线程方式的系统开销更小。资源浪费是一方面,沟通简单也是另一方面的优势。有了这两点的内容,是不是可以选择多进程呢?线程池的内容你在工作中使用过线程池吗?为什么要使用线程池?这个问题有点尴尬,为什么这么说呢?如果你说你没用过,那你相当于面试官只写了CRUD逻辑业务,其他的内容你都没有。如果你说你用过,那你就得回答下一系列关于线程池的问题。这款风扇还是很推荐的,说实话,就算你没用过,那也别乱说,不然你就得往自己挖的坑里跳了。那么我们来分析一下为什么要使用线程池。首先,我们要考虑一件事。如果不使用线程池,创建线程有什么坏处吗?在java中,如果每次请求到来都创建一个新的线程,对服务器的资源消耗是不是有点大?创建一个线程,销毁一个线程,创建一个线程,销毁一个线程,然后在各个线程之间来回切换。来来回回,是不是觉得资源浪费了?那么线程池会不会避免这种情况呢?优点来了1.创建/销毁线程会消耗系统资源,线程池可以复用创建的线程。虽然这个优势很明显,但这并不是主要原因。主要原因是:控制并发数。并发量过大可能导致资源消耗过大,导致服务器崩溃。(主要原因)可以统一管理线程,分析一下线程池的原理,longkeepAliveTime,TimeUnitunit,BlockingQueueworkQueue){this(corePoolSize,maximumPoolSize,keepAliveTime,unit,workQueue,Executors.defaultThreadFactory(),默认处理程序);参数那么多,到底是什么意思呢?intcorePoolSize:线程池的最大核心线程数。intmaximumPoolSize:线程池中线程总数的最大值。longkeepAliveTime:非核心线程空闲超时。TimeUnit单位:keepAliveTime的单位。BlockingQueueworkQueue:一个阻塞队列,维护着等待执行的Runnable任务对象。corePoolSize核心线程最大值:如何确定这个值?总的来说,这道题比较难。如果面试官问出这个问题,一般的学生肯定脑袋都大了。我知道这意味着什么,但我该如何设置它以及如何定义它?其实有个计算公式:最佳线程数=((线程等待时间+线程CPU时间)/线程CPU时间)*CPU数量=(线程等待时间与线程CPU时间之比+1)*CPUnumberthreadwaitingtime百分比越高,需要的线程越多。线程CPU时间的比例越高,需要的线程就越少。maximumPoolSize:线程池总线程数的最大值,其实就是核心线程数+非核心线程数。如果空闲状态超过这个值,就会被销毁。BlockingQueue:阻塞队列看起来像MQ中的东西。当我们想到队列时,我们可以想到生产者和消费者。这时候,问题就出现了。为什么会有阻塞队列?是否出现了消费者模型,生产者一直在生产资源,消费者一直在消费资源,资源存放在一个缓冲池中。当我们实现这种模式时,多个线程操作共享变量,带来了线程安全问题,导致重复消费和死锁。这时候就会出现阻塞队列。当缓冲池为空时,我们需要阻塞消费者唤醒生产者;当缓冲池已满时,我们需要阻塞生产者并唤醒消费者。BlockingQueue提供了一种线程安全的队列访问方式,很多并发契约下的高级同步类的实现都是基于BlockingQueue。也就是说,你只负责生产和消费,安全问题,JDK给你担保。说到这里,我们就不继续往下延伸了,下次阿粉就直接来BlockingQueue来完整分析一下。应该是BlockingQueue绝对需要很长的内容才能解释清楚。分析完里面的参数,这时候就得看线程池是怎么处理线程任务的,不然怎么跟面试官打架。线程池如何处理内部线程任务publicvoidexecute(Runnablecommand){if(command==null)thrownewNullPointerException();intc=ctl.get();//1、当前线程数小于corePoolSize,则调用addWorker创建核心线程执行任务if(workerCountOf(c)