我从一本公认的样本书中看到了这一点,所以很难回答那些我不理解的东西。
一个名为DataflightsService的类包含一个名为FlightFileAccess的私有静态变量,每当我们为DataflightsService创建一个新对象时,它就会被实例化,因为FlightFileAccess在构造函数中启动它
即
public class DataflightsService{
private static FlightFileAccess fileAccess=null;
public DataflightsService(String path){
fileAccess=new flightFileAccess(path);
}
public boolean removeflight(String code){
//We use this static instance that wraps functionality to remove a flight
fileAccess.remove(code);
}
}
对我而言,这意味着每次我们创建DataflightsService
的实例时,构造函数都会一直使用不同的对象来表示静态变量FlightFileAccess
在原始的
FlightFileAccess
类中:我们有一个同步RandomAccessFile
的删除方法
Class FlightFileAccess{
private RandomAccessFile database = null;
private boolean remove(String code){
// Other code goes here and there
synchronized (database) {
//Perform deletion code
}
}
因为我们使用FlightFileAccess
的不同引用,我们也使用RandomAccessFile
的不同引用?
这意味着将FlightFileAccess
作为静态服务并不在synchronize
上RandomAccessFile
用于DataflightsService
,因为每次都是FlightFileAccess
每个DataflightsService
实例在随机访问文件上做他们的事情忽略同步。
而不是在静态启动器中实例化DataflightsService
。我是对的吗?
我希望尽可能多的解释提供能够根据需要多次实例化DataflightsService
的最佳方法(假设想象每个客户端都有自己的{{1}}实例)并且之后能够在文件上进行同步以进行删除,例如,以便几个客户端不会访问该文件。对不起,我需要为每个客户提供一个{{1}},但没有cookie。
答案 0 :(得分:0)
您的示例不会编译,因为构造函数的名称与该类不匹配。但是如果你的意思是命名构造函数public DataflightsService()
,那么部分问题是每次创建新对象时都要覆盖静态变量。
听起来你想要只将这个静态变量初始化一次。通常你只需要用private static final FlightFileAccess fileAccess = new FlightFileAccess();
直接赋值变量,或者如果你想添加更多逻辑,就像你有一个构造函数一样,你可以使用静态初始化程序块,如下所示:
public class Dataflights {
private static final FlightFileAccess fileAccess;
static {
// Static initializer block gets run once when the class is first referenced.
// Not usually used unless you want to add more logic besides just initializing variables.
fileAccess = new FlightFileAccess();
}
private final String path;
public final int id;
public Dataflights(String path) {
this.path = path;
this.id = fileAccess.generateId();
}
static class FlightFileAccess {
private volatile int nextId = 0;
synchronized public int generateId() {
return nextId++;
}
}
public static void main(String[] args) {
Dataflights d = new Dataflights("my/path");
System.out.println("Id is: " + d.id);
}
}
有许多方法可以处理争用。如果您不熟悉Java并发,我建议Java Concurrency in Practice。
您在FlightFileAccess课程中处于正确的轨道上。我无法查看详细信息,但您可能还希望在synchronized
方法的签名中使用remove()
关键字来保护整个函数。然后,一旦你有工作,使用更紧密的目标synchronize {...}
块来减少必须单线程的代码量。