Cha*_*les 5 java static findbugs
我有一个显示部门文档的项目.我将所有文档(从数据库中获取)存储在静态arrayList中.每隔X小时,我就根据数据库中的新doc(如果有的话)重建了arrayList.还有一个静态变量来控制重建该数组,在执行重建任务的方法中设置和取消设置.每个访问服务器的Web浏览器都将创建此类的实例,但doc arrayList和该控件变量在所有类实例之间共享.
Find-Bugs工具抱怨"从实例方法someClassMethod写入静态字段someArrayName和someVariableName".似乎这不是好事(让类实例方法写入静态字段).有没有人有好的建议如何解决这个问题?谢谢.
根据FindBugs错误描述:
ST:从实例方法写入静态字段(ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD)
此实例方法写入静态字段.如果操作多个实例并且通常是不好的做法,这很难得到纠正.
除了并发问题之外,它意味着JVM中的所有实例都在访问相同的数据,并且不允许两个单独的实例组.如果你有一个单独的"manager"对象并将它作为构造函数参数或至少作为setManager()方法参数传递给每个实例,那会更好.
至于并发问题:如果你必须使用静态字段,你的静态字段应该是最终的; 显式同步很难.(如果你正在初始化非最终静态字段,还有一些棘手的方面,除了我对Java的了解,但我认为我已经在Java Puzzlers书中看到过它们.)至少有三种方法可以解决这个问题(警告,未经测试的代码如下,在使用前先检查):
使用线程安全的集合,例如Collections.synchronizedList包裹在未以任何其他方式访问的列表中.
static final List<Item> items = createThreadSafeCollection();
static List<Item> createThreadSafeCollection()
{
return Collections.synchronizedList(new ArrayList());
}
Run Code Online (Sandbox Code Playgroud)
然后当你从一个实例替换这个集合时:
List<Item> newItems = getNewListFromSomewhere();
items.clear();
items.add(newItems);
Run Code Online (Sandbox Code Playgroud)
这个问题是,如果两个实例同时执行此序列,您可以得到:
Instance1:items.clear(); Instance2:items.clear(); Instance1:items.addAll(newItems); Instance2:items.addAll(newItems);
并获得一个不符合所需类不变量的列表,即在静态列表中有两组newItems.因此,如果要将整个列表清除为一步,并将第二步添加为项,则此方法不起作用.(但是,如果您的实例只需要添加一个项目,则items.add(newItem)可以安全地从每个实例中使用.)
同步对集合的访问.
你需要一个明确的同步机制.同步方法不起作用,因为它们在"this"上同步,这在实例之间不常见.你可以使用:
static final private Object lock = new Object();
static volatile private List<Item> list;
// technically "list" doesn't need to be final if you
// make sure you synchronize properly around unit operations.
static void setList(List<Item> newList)
{
synchronized(lock)
{
list = newList;
}
}
Run Code Online (Sandbox Code Playgroud)使用AtomicReference
static final private AtomicReference<List<Item>> list;
static void setList(List<Item> newList)
{
list.set(newList);
}
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
15253 次 |
| 最近记录: |