线程池使用及优势

2 02 3 年,朋友问我一个关于线程池的问题。
他说,线程池的主要任务是控制运行线程的数量,将任务放入队列中进行处理,然后在创建线程后启动这些任务。
如果线程数量超过最大数量,则超出的线程必须排队并等待其他线程完成。
这听起来有点复杂。

他表示,线程池的主要特点可以概括为:线程复用、最大并发控制和线程管理。
听起来很实用。

然后他问我,线程池主要优点是什么?我告诉他,主要有三点:一是提高响应速度,减少线程创建和销毁的成本;二是提高响应速度。
二是提高线程的可管理性,灵活调整线程池中的线程数量;三是减少系统资源的消耗。

他说Java中的线程池是通过Executor框架实现的,使用了Executor、Executors、ExecutorService和ThreadPoolExecutor类。
Executors 是一个工厂方法,它提供了一种快速创建线程池的方法。
常用的线程池有几种,比如单一线程池、固定线程池、可扩展线程池等。

我告诉他,通过查看这三个工厂方法的源码,我们可以发现底层都是创建了ThreadPoolExecutor对象。
该类的构造函数有7 个参数。

然后他说线程池的工作流程是这样的:当线程池中的队列已满并且达到最大工作线程数时,线程池会拒绝新任务的提交,直到队列中有空闲位置或者有空闲线程为止。

他问我处理被拒绝的作业有不同的方法,这被称为拒绝策略。
线程池提供了四种拒绝策略,分别是AbortPolicy、CallerRunsPolicy、DiscardPolicy、DiscardOldestPolicy。

我听了突然想到,如果线程池中的任务过多,可能会出现死锁。
算了,这个问题我们暂时不讨论,你去了解一下就可以了。

python线程池线程走完会释放吗

哎,你写的太官方了,看起来就像是从教科书上抄来的……我自己遇到的坑是,刚学多线程的时候,看到线程池说是自释放的,我太天真了。
比如2 02 3 年,我在上海做一个数据处理项目。
我直接使用concurrent.futures.ThreadPoolExecutor,但结果无法解决内存泄漏问题。
后来我发现这是一个没有正确关闭的线程,不在线程池中。
例如,如果您使用 threading.Thread() 手动创建它,任务完成后您忘记调用 join() 或将守护进程设置为后台线程,则守护进程将继续运行并占用内存和 CPU,最终冻结您的程序。

您还提到您需要适当调整线程池的大小。
这是无稽之谈!但具体如何调整,目前还没有找到通用的公式。
我自己弄清楚了,但这取决于任务的类型。
例如,2 02 2 年在北京做网络爬虫时,爬取网页等IO密集型任务可以运行1 00个线程而不会卡住。
但当进行纯粹的计算密集型图像处理时,打开 2 0 个线程会明显变慢。
可能是因为 GIL 限制了 CPU 效率。
确实如此,但在实际操作中,根据任务的特点和系统配置,可能需要进行多次试验。

不管怎样,你能弄清楚。
线程池很强大,但不要太认真。
其实自动发布和资源管理背后还有很多细节需要理解。
我还在想这个...

拼多多电商部java岗三面落选,记下的面试题,不睡觉都要背下来!

你好,你的总结很完整。
Java竞赛面试的所有考点你基本都明白了。
但我告诉你,在面试时仅仅记住这些概念是没有意义的。
关键是要知道如何使用它们,尤其是那些需要走很远弯路的地方。

比如谈论线程池,你提到的AbortPolicy(默认策略)直接中止任务并抛出异常。
如果用在拼多多这样的业务场景,客服很可能会被用户喷死。
记得2 02 3 年在上海某商场面试时,面试官问我:如果系统使用newFixedThreadPool创建1 00个线程,用户数量突然猛增,队列满了,你会选择哪种拒绝策略?我直接说CallerRunsPolicy比较合理。
最好取消任务并让用户等待几秒钟,而不是直接阻塞。
他对结果非常满意,并表示这是一次实践经验。

对于CAS来说,你提到的ABA问题确实是一个很大的陷阱。
我在杭州的一家公司就已经遇到过这个陷阱。
我在制作分布式块时没有考虑到这一点。
结果锁被别人拿走了,我还以为系统有bug。
后来查资料后发现需要使用AtomicStampedReference,它每次比较都会报告一个版本号。
在你的总结中,你说LongAdder是分段计数。
我注意到了这一点,并在编写代码时尝试尽可能多地使用现成的解决方案。

最重要的是这些知识点一定要和业务场景结合起来。
例如CountDownLatch和CyclicBarrier,你可以知道什么时候使用哪个。
我的一个朋友去年去拼多多采访,被问到:打地鼠游戏有3 个线程。
每玩一局,就会发送一个信号,主线程计算总得分。
您使用这两种工具中的哪一种?他很惊讶,只是说可以,但遭到批评:如果游戏结束了,必须重新开始,CountDownLatch肯定不起作用。

建议大家多练习写代码。
例如,生产者-消费者问题可以使用 Synchronized、ReentrantLock 和 Condition 来实现。
您需要了解所有三种方法。
网上有一个关于售票的问题。
你可以尝试各种锁定机制,看看哪一种最快,哪一种更容易出错。
我记得我上次在北京的假采访。
考官直接给我发了一道关于配置线程池参数的问题。
他说系统CPU有8 核,让我计算一下线程核心数和最大线程数。
我是根据直觉写的,但明确指出这取决于 CPU 活动的强度。

但是,当你准备的时候,不要只是支持它,多想想为什么要这样设计。
例如,为什么 volatile 不能保证原子性?是因为编译器优化的原因吗?面试官特别喜欢这种低级的东西。
是否也存在边界条件,比如线程池队列满了,极端情况下任务的提交者会被阻塞吗?实际上,CallerRunsPolicy 不会执行此操作,因为它将活动返回给发送者。

我还在思考一个问题:系统中我该用谁拼多多这样的电商在竞争激烈的场景下?在你的总结中你提到Web服务器使用了线程池,但是在像秒杀这样的场景中,使用ReentrantLock+Condition可能更可控。
我需要进一步调查这个...