阿里巴巴面试题及答案汇总

1、Linux下如何查看/监控JVM内存?

本地(带图形环境):jvisualvm

线上(无图形环境):看总内存用top,看详细信息用jmap dump出来分析

Top nmon

查看整个JVM内存状态 jmap -heap [pid] 要注意的是在使用CMS GC 情况下,jmap -heap的执行有可能会导致JAVA 进程挂起

查看JVM堆中对象详细占用情况 jmap -histo [pid]

导出整个JVM 中内存信息 jmap -dump:format=b,file=文件名 [pid]

jhat是sun 1.6及以上版本中自带的一个用于分析JVM 堆DUMP 文件的工具,基于此工具可分析JVM HEAP 中对象的内存占用情况 jhat -J-Xmx1024M [file] 执行后等待console 中输入start HTTP server on port 7000 即可使用浏览器访问 IP:7000

eclipse Memory Analyzer Eclipse 提供的一个用于分析JVM 堆Dump文件的插件。借助这个插件可查看对象的内存占用状况,引用关系,分析内存泄露等。

kill -3 [pid] 在Linux 上找到Java所在的进程号,然后执行以上命令,线程的相关信息就输出到console

jstack jstack 是sun JDK 自带的工具,通过该工具可以看到JVM 中线程的运行状况,包括锁等待,线程是否在运行 执行 jstack [pid] ,线程的所有堆栈信息

"http-8080-10" daemon prio=10 tid=x0a949bb60 nid=0x884 waiting for monitor entry [...]

"http-8080-10" 这个线程处于等待状态。 waiting for monitor entry 如果在连续几次输出线程堆栈信息都存在于同一个或多个线程上时,则说明系统中有锁竞争激烈,死锁,或锁饿死的想象。

“http-8080-11” daemon prio=10 tix=xxx nid=xxx in object.wait() [...] java.lang.Thread.State:waiting (on object monitor) 该表示http-8080-11的线程处于对象的Wait 上,等待其他线程的唤醒,这也是线程池的常见用法。

“Low Memory Detector”daemon prio=10 tix=xx nid=xxx runnable [...] java.lang.Thread.State:runnable 表示“Low Memory Detector” 的线程处于Runable状态,等待获取CPU的使用权.

查看Pid 文件

/proc/18225/status or io 信息

2、高并发,执行耗时短的任务,还有低并发,执行耗时长的任务,各自选取什么样的线程池会比较合理?为什么?如果业务场景是高并发,且任务耗时长时,有什么解决思路?

线程池的关键点是:1、尽量减少线程切换和管理的开支; 2、最大化利用cpu。 对于1,要求线程数尽量少,这样可以减少线程切换和管理的开支; 对于2,要求尽量多的线程,以保证CPU资源最大化的利用。 所以对于任务耗时短的情况,要求线程尽量少,如果线程太多,有可能出现线程切换和管理的时间,大于任务执行的时间,那效率就低了; 对于耗时长的任务,要分是cpu任务,还是io等类型的任务。如果是cpu类型的任务,线程数不宜太多;但是如果是io类型的任务,线程多一些更好,可以更充分利用cpu。 所以: 高并发,低耗时的情况:建议少线程,只要满足并发即可;例如并发100,线程池可能设置为10就可以 低并发,高耗时的情况:建议多线程,保证有空闲线程,接受新的任务;例如并发10,线程池可能就要设置为20; 高并发高耗时:1要分析任务类型,2增加排队,3、加大线程数

对于高并发耗时长的情况,我认为,思路就是把一个难以解决的问题转化成我们已知的已经有解决方案的问题,以此来解决。 所以 ,高并发又耗时长,可以转化为 1、高并发,耗时短的问题 –> 异步处理+回调,和情况1吻合 2、低并发,耗时长的问题 –> 前端加load balance,把高并发分摊成若干低并发,和情况2吻合 其实说到核心,如果真遇到高并发耗时长的场景,只能是加机器,加计算单元(无论是异步加回调还是load balance)


经验分享 程序员 微信小程序 职场和发展