我想拥有一个类的多个实例,但是能够一次更改一个变量的所有非静态实例。也许这段代码会更清晰:
public class Example {
public int _x; //_x and _y are NOT static
public int _y;
Example (int x, int y) {
_x = x;
_y = y;
}
public void zeroThem() {
_x = 0;
_y = 0;
}
}
zeroThem()
方法的重点是我可能有
Example A = new Example(1, 2);
Example B = new Example(3, 4);
但是一旦我拨打类似的电话:A.zeroThem();
以下是正确的:
A._x == 0;
B._x == 0;
A._y == 0;
B._y == 0;
有没有办法使_x和_y保持静态?
这可以通过以下修复程序来实现:
volatile
Example
实例的静态synchronized静态集合并对其进行迭代。zeroAll
调用实例方法zeroThem
。 zeroAll
可以实现为非静态的,但是一旦它影响Example
的all实例,最好将其标记为static
。public class Example {
private static List<Example> all = Collections.synchronizedList(
new ArrayList<>());
public volatile int _x; //_x and _y are NOT static
public volatile int _y;
Example (int x, int y) {
this._x = x;
this._y = y;
Example.all.add(this);
}
public void zeroThem() {
_x = 0;
_y = 0;
}
public static void zeroAll() {
synchronized(Example.all) {
Example.all.forEach(Example::zeroThem);
}
}
}
更新使用WeakReference
和ReferenceQueue
解决注释以解决内存泄漏问题:
import java.lang.ref.*;
import java.util.*;
public class Example {
private static final ReferenceQueue<Example> refQueue = new ReferenceQueue<>();
private static final List<WeakReference<Example>> all = Collections.synchronizedList(new ArrayList<>());
public volatile int _x; //_x and _y are NOT static
public volatile int _y;
Example (int x, int y) {
this._x = x;
this._y = y;
Example.all.add(new WeakReference<>(this, refQueue));
}
public void zeroThem() {
_x = 0;
_y = 0;
}
public static void zeroAll() {
synchronized(Example.all) {
Example.all.removeIf(ref -> ref.get() == null); // delete non-existing instances
Example.all
.stream()
.map(WeakReference::get)
.forEach(Example::zeroThem);
}
}
}