多线程和线程池面试题

这是一篇关于 多线程和线程池面试题 的文章。

线程池

我们知道线程的创建和销毁是比较耗时的操作,因此,如果我们需要创建大量的线程,那么势必会影响程序的运行效率。因此,我们可以利用线程池这个池化的思想来解决这个问题。

线程池在初始化的时候,就会创建一组线程,任务被提交会以队列的形式加入到线程池中,线程池中的线程会去执行任务队列中的任务。当一个线程执行完任务后,它会再从任务队列中取出下一个任务来执行。

有两种比较常见的线程池形式,一种是固定线程池(FixedThreadPool),另一种是动态线程池(CachedThreadPool)。前者线程池的大小是固定的,后者会在空闲时销毁线程,线程池的大小会根据需要自动调整。

但根据开发规范和经验,我们应该禁止使用这两种线程池,而应该手动 new ThreadPoolExecutor 创建线程池。这是因为当任务很多并且处理不来的时候 FixedPool 会因为任务被积压到任务队列中,撑爆内存,引起 OOM(Out Of Memory)。而 CachedPool 会不断的创建线程来执行任务,这同样会导致撑爆内存,引起 OOM,同时过多的线程切换也会引起严重的性能损失。

大多数情况下,我们需要的是闲时保留一定的线程(核心线程),忙时创建线程。直到达到设定的最大线程数时停止创建。来不及处理的任务放到定长的任务队列中,当任务队列满的时候触发拒绝策略。在线程池闲下来的时候销毁线程,将线程池中的线程数量回收到核心线程数。