Sco*_* C. 12 java scope static-members
我在我的日志记录类中定义了一个静态对象,其行如下:
class myLoggingClass {
static java.util.Properties properties;
...
...
}
Run Code Online (Sandbox Code Playgroud)
根据我的参考书,这意味着属性对象由我的类的所有实例共享.
我觉得这个定义不够.我正在编写一个在我们项目的每个应用程序中多次调用的类.
此外,我们的项目使用在同一个tomcat容器中运行的多个Web服务.每个Web服务可能有多个线程.
在主机上运行的Java虚拟机还可以运行一个或多个Web服务客户端应用程序,这些应用程序在tomcat外部运行.
因此,通过这个定义,我可能让tomcat运行带有线程的多个Web服务,每个线程都有几个对象,这些对象可能包含我的类的实例.
也可能有一个或两个Web客户端在tomcat之外运行,但在同一个JVM中.将所有的我的课分享这些实例的相同属性对象?这将使其成为JVM范围的.
如果静态对象不是 JVM范围的,那么有人知道每个对象存在的级别吗?每个tomcat容器一个?每个Web服务一个,每个独立Web服务客户端应用程序一个?
原因是:当我更新我的属性时,我从java.util.Properties获得了java.lang.ConcurrentUpdateException.
我正在使用静态布尔变量来在我的类更新时"锁定"属性对象,但这并不能防止异常发生.
这让我相信我的类中使用的静态对象可能与java.util.Properties中使用的静态对象没有相同的范围级别......但这只是猜测.
谢谢你的帮助.
Jon*_*eet 18
静态不是"所有类的实例共享" - 它们与实例无关 ; 它们属于该类型本身.特别是,静态变量在没有创建任何实例的情况下完全可用.
这给出了静态范围的线索:它们由Class表示包含类的对象确定范围,而包含类的范围又由ClassLoader加载它的范围限定.
根据库的放置位置,静态变量可能是JVM范围的或Web应用程序范围的 - 或者可能是介于两者之间的东西,如果Tomcat支持多个托管(我不记得随便).
查看Tomcat文档,了解库的布局方式以及它们与类加载器的关系.例如,这里是Tomcat 6.0 ClassLoader的操作指南,以及5.5的等价物.
您的布尔"锁定"如何工作?你应该使用一个正确的lock(synchronized)来确保每次使用属性对象(包括读取和写入,包括在整个迭代过程中锁定)都被适当地锁定.
Properties您是否考虑将其视为不可变的,而不是更改"实时" 对象 - 因此,当您想要更新属性时,您需要复制,更改它,然后将副本设置为"实时"版本?你仍然需要阻止两个不同的线程同时进行更改(或者你会丢失一些),但它可能会使阅读方面更容易,更有效.
您可能会发现,对于static已加载您的类的ClassLoader,此类变量的范围仅限于一个.我不确定Tomcat如何安排其ClassLoader,因此很难说该范围在该环境中的范围.
可能的原因ConcurrentModificationException是您在一个线程中迭代Properties对象的值/条目,而另一个线程同时修改它。你不可以做这个。
您能否详细说明一下您在这里提到的锁定机制:
当我的类更新它时,我使用静态布尔变量来“锁定”属性对象,但这并不能阻止异常的发生。
?
因为听起来不像是在使用 Java 中内置的锁定和同步方法。
像这样的事情应该可以防止线程在另一个线程更新它时读取 Properties 对象:
static Object lockObject = new Object();
...
synchronized(lockObject) {
// access the Properties object
}
Run Code Online (Sandbox Code Playgroud)
请注意,每次访问 Properties 对象(读取或修改它)时都需要执行此操作。
另外,我永远不会推荐静态对象在所有实例或静态 lockObjects 之间共享数据 - 全局数据是邪恶的 - 但听起来好像你出于某种原因需要它。
| 归档时间: |
|
| 查看次数: |
7246 次 |
| 最近记录: |