Java 中如何优雅的使用线程池

2019-07-15 10:11:39 +08:00
 liuxingchina

如题,线程的资料面试题看了一大堆,但是用的很少,大家平时是怎么使用的。上次我是在类里直接写了 static 的 ExecutorService 然后使用的,不知道对不对

6154 次点击
所在节点    Java
11 条回复
justRua
2019-07-15 10:20:49 +08:00
ExecutorService 里面的构造的线程的队列是无界的,按照阿里手册上的说法是不推荐直接使用,在并发量不大时我是直接用用这个。。。公司项目里是用 spring 配置的线程池 ThreadPoolTaskExecutor,之前公司有用 ExecutorService,在上面包装了一层加了个 Semaphore,线程数量超过最大值时阻塞不让排队。
xiaoidea
2019-07-15 10:23:14 +08:00
没问题。
建议:1. 不要直接用 Executors 静态方法创建线程池,而是用 ThreadPoolExecutor 的构造方法创建。2. 用 guava 的 MoreExecutors#listeningDecorator 对线程池包装,后续很多 guava 的工具方法可以使用
lihongjie0209
2019-07-15 10:25:48 +08:00
@justRua 线程池本身就可以配置拒绝策略的, 为什么还要自己使用 Semaphore?
lihongjie0209
2019-07-15 10:26:55 +08:00
最好是一个 jvm 一个或者两个线程池, 不要在类中实例化, 不然和裸使用线程没区别
justRua
2019-07-15 10:30:46 +08:00
@lihongjie0209 别人写好的,猜他意图应该是任务来了不让排队,也不让拒绝,就阻塞在那等待消费,感觉和 SynchronousQueue 有点类似吧,业务场景是做 ETL,提交的任务必须跑不能丢弃。
lihongjie0209
2019-07-15 10:43:12 +08:00
@justRua 既然提交的任务不能丢弃, 为什么不用无界队列?

"线程数量超过最大值时阻塞不让排队。"

这相当于使用 AQS 实现的 Semaphore 作为一个隐含的队列来用
airfling
2019-07-15 11:19:37 +08:00
我的一般策略是一个应用一个,要么单例,要么全局。
choice4
2019-07-15 12:25:34 +08:00
现在直接写 CompletableFuture 了。
Aresxue
2019-07-15 16:26:05 +08:00
使用 new ThreadPoolExecutor 创建 static 的线程池,线程池要共享的,不然和裸开线程区别不是很大,看情况有必要的话设置为 final 的而且是守护线程。
SkyLine7
2019-07-16 16:51:27 +08:00
自己写一个线程池工具类,包含和核心线程数,最大线程数,阻塞队列,拒绝策略....网上这东西很多的
qwertyegg
2019-07-19 23:52:26 +08:00
forJoinPool?

~~~java
val forkJoinPool = ForkJoinPool(PARALLELISM)
forkJoinPool.submit{
some_parallel_stream_job
}.get()
~~~

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/582998

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX