曾见过一个大牛的观点:
他说的是否有道理?
现在有这样一个需求:
如果我把这个 thread pool 定义为 static ,会有什么坏处吗?
1
bigapple111 2016-08-18 12:08:44 +08:00
如果只是说坏处的话,如果涉及到应用场景的话,我相信每个人都有自己的想法,
这个问题应该是 “如果我把这个 thread pool 定义为 static ,会有什么好处吗?” 前文提到 “内存中只保留一份,不需要频繁创建和销毁” 你的应用需要频繁创建 ThreadPool ? |
2
miaoxia OP @bigapple111 感谢你的回复
前文提到的只是静态变量的优点,和场景无关。 应用肯定不需要频繁创建 threadPool ,而且想如何去避免频繁创建 threadPool 。 所以才会去假设,将 threadPool 设置成 static 后,会不会实现我预期的目的, 而且是否可能带来什么问题。 |
3
miaoxia OP @bigapple111
如果不设置为 static ,每 new 一个子类的时候 都会创建一个新的 threadPool 吧 我就是希望可以避免这个问题,能让所有子类共享父类的 threadPool 。 |
4
tobyxdd 2016-08-18 13:02:42 +08:00
没必要为了别人因为他们项目特点总结的条条框框影响自己项目架构 ThreadPool 弄成 Static 再正常不过了
|
5
ghostsf 2016-08-18 13:27:47 +08:00
根据实际需求来,很明显,这里需要 static
|
6
bigapple111 2016-08-18 13:41:11 +08:00
@miaoxia
如果不设置为 static ,每 new 一个子类的时候 都会创建一个新的 threadPool 吧 我就是希望可以避免这个问题,能让所有子类共享父类的 threadPool 。 static 确实能避免上述的问题,大胆的写吧 |
7
bigapple111 2016-08-18 13:43:17 +08:00
@miaoxia 或者你自己实现一个单例的 ThreadTaskService ,父类里面定义这个 Service,也一样能达到你想要的效果
|
8
SoloCompany 2016-08-18 13:44:18 +08:00 via iPhone
1 static 不应该使用一定意义上是正确的
2 threadpool 应该注入来解决 |
9
shimanooo 2016-08-18 13:53:11 +08:00
静态常量可以有
|
10
YORYOR 2016-08-18 14:26:22 +08:00
static 可以,系统启动时 生成一个单例的 pool 也可以
|
11
cloudzhou 2016-08-18 15:10:34 +08:00
1 使用单例化
2 注入 |
12
miaoxia OP |
13
miaoxia OP @bigapple111
@YORYOR @cloudzhou 感谢回复 单例是一种解决方式 不过仍有些疑惑 单例不也是通过 static 方式实现的吗 是否有以下假设: 将需要共享的元从宿主中分离出来,做成单例(仍是 static 的) 就避免 static 可能产生的问题? |
14
miaoxia OP @SoloCompany 非常感谢
开拓了新思路 再请教下 通过 Constructor 还是 seter 来实现呢? 在我看来既然已经实现了异步方式, threadPool 的实例是一定要注入的 既 使用 Constructor 方式来实现 但在子类的 Constructor 里,还需要传入其他业务相关的参数 感觉一个业务类的 Constructor 里并列注入一个 threadPool ,看起来有点突兀- - 由于业务能力尚浅,可能有些比较幼稚的观点,请指教 |
16
YORYOR 2016-08-18 15:39:44 +08:00
@miaoxia 单例可以通过 static 实现,也可以你自己在系统启动时仅在系统内 生成一个 final 类型的即可,类似 spring 中的 bean 貌似都是单例的
|
17
slixurd 2016-08-18 16:24:17 +08:00
@YORYOR Spring 的 Bean 是 singleton 这个只是 scope 默认配置而已,你配个 prototype 就不一样了。
单例什么的和 static field 没有必然关系,只是因为 static field 一定只存在一份,所以经常用来做单例而已。 什么 double check idiom 之类的 |
18
asj 2016-08-18 17:24:53 +08:00
只应该拿来定义常量。
如你问题里描述的需求,应该用 Spring 或者其他框架来管理对象的生命周期,而非依赖语言特性。 |
19
SoloCompany 2016-08-18 21:02:30 +08:00 1
@miaoxia
static 不建议使用主要有两点:容易造成内存泄漏,强耦合,强耦合的问题尤其严重。 注入的方式有很多种,不依赖框架的话,构造方法或者 setter 方法或者单独的 init 方法都是可取的,用 Spring 之类的依赖注入当然就更简单了,其它比如容器提供 jndi 注册也是一种选择,总而言之有很多种方法可以实现单例, static 是看上去省事但却是最坏的选择 |
20
hinkal 2016-08-19 01:06:30 +08:00 1
这个需求很适合 static ,不过可以考虑下真的是这个需求吗?譬如“多个子类想共享一个父类的线程池”,高耦合,子类想访问线程池中的对象?或许可以抽象出一个线程池控制器,通过代理者进行交互。因此最好从设计上改变,减少不必要 static 的使用。
|
21
georgema1982 2016-08-19 02:17:14 +08:00 1
一般的原则是 static 和变量可接受的组合是 final static ,即用来定义常量;不要有任何 static 的方法。现代 java 编程里,如果出现非 final 的 static 申明,基本上都是不可接收的
|
23
miaoxia OP |
25
miaoxia OP @hinkal 感谢您的回复
您给出的设计给了我很大启示 还想和您探讨下 “'多个子类想共享一个父类的线程池'会造成高耦合” 的问题 您是指 多个子类 与 共同父类 之间的耦合吗 如果我在父类中将与 threadPool 相关的操作 写成模板 在子类中去重写实际处理业务的方法 对于子类而言 是否异步是透明的(或者尽量透明) 这样还会产生耦合的现象吗 可能我对耦合的定义仍然不是那么明晰 请指教 |
26
miaoxia OP @georgema1982 感谢回复
您的观点我完全赞同 只是实际工作中我在极力避免的过程中会遇到问题 除本文所指问题外 例如 Utils 类中,大家的惯例是 private Constructor public 方法全部 static 您觉得这样的情况如何避免? |
27
miaoxia OP @hinkal 再补充下
我的问题中提到"子类去 submit 一个 runnable" 如果修改我上面说的实现,做出以下的实现: 1. 父类中的 thread pool 相关操作对于每个子类都是相同的,是一个共同的模板。 2. 由于是操作相同,当父类的线程机制做调整时,其他全部子类同时受影响。(子类是并列的概念,只是业务有区分) 如果实现共享父类的 thread pool ,会让全部的并行子类都单向依赖这个 thread pool 。 会产生高耦合的危害吗? 换句话说,当这个被依赖的模块,对于依赖它的模块的处理是统一的。 这样的情况,会产生高耦合的危害吗? |
28
shyling 2016-08-19 10:15:51 +08:00 via Android
那些说注入的仿佛自己没有间接用 static 。。。乖乖用 Executor 不就好咯。。。接口标准库都封装好了。
|
29
hinkal 2016-08-19 12:12:52 +08:00
@miaoxia 如果“父类中的 thread pool 相关操作对于每个子类都是相同的”,那么放父类中做成”模板“,并且把对父类 threadpool 的操作放在父类方法中,这样对于子类,弗雷德 thread pool 是透明的,这样就不会高耦合吧。如果让子类都直接访问父类 static 对象,不符合迪米特法则,就是高耦合。
|
30
hinkal 2016-08-19 12:19:13 +08:00
@miaoxia ”您是指 多个子类 与 共同父类 之间的耦合吗 “不是,我指的是多个子类之间的耦合。本来,子类和父类之间不存在高耦合的问题,因为继承的目的就是公有一些方法和属性,然而你把所有子类产生的对象提交到父类的一个线程集合里,强行让他们互相可以引用,这样就让子类之间耦合起来了。
|
31
jason19659 2016-08-19 15:07:13 +08:00
你也知道静态变量的特点了,在符合这个特点,或者是使用这个最方便的时候可以用
|
32
TakWolf 2016-08-20 00:32:00 +08:00
凡是单例模式的通常都应该用 static
基于回收池或者重用池模式的,回收池实例声明周期为逻辑声明周期一致,因此,如果你是对 app 的回收池,通常他也是单例静态的 |
33
georgema1982 2016-08-20 02:07:40 +08:00
@miaoxia 说明“大家”都还在用老式的设计模式,即用 java 本身的特性来管理一个类的生命周期。现代的设计模式是不要自己实现生命周期,把所有 java 类都写成 pojo 。这种 pojo 不应该有非 public 的 constructor ,不应该存在 static 的方法。你们公司里如果还在用这种老式的设计模式的话,我第一反应就是你们公司不做单元测试
|