2015-04-03 54 views
-1

我从一本公认的示例书中看到了这一点,所以很难回答,然后有些我不明白的地方。静态变量,线程和构造函数Java

称为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); 
    } 
} 
开始其被实例化

对我来说,这意味着我们每次创建的实例10,在构造函数中使用的是不同的对象所有的时间静态变量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 
     } 
    } 

是因为remove方法我们正在使用不同的参考FlightFileAccess我们也使用不同的参考RandomAccessFile

这意味着,有FlightFileAccess静态服务不会成为这里synchronizeRandomAccessFile,因为它是每次所以每个DataflightsService实例将做随机访问的文件忽略了同步他们的事一个新的。与在静态启动器中实例化FlightFileAccess相反。我对吗?

我会尽可能多的解释,以提供最好的方式来实例化DataflightsService多少倍(我们可以说想象每个客户端都有自己的实例DataflightsService),然后才能够同步在一个文件中删除例如,以便没有几个客户访问该文件的混乱。对不起,我需要为每个客户端添加一个DataflightsService bc没有cookie。

+1

请编辑您的问题,并将代码格式化为代码,并将其缩进。 – 2015-04-03 15:47:10

+0

仅仅因为你在一本书中找到了建议,这并不会自动提供建议。构造函数无条件地分配一个静态字段?这听起来像严重不好的设计。 – 2015-04-03 17:09:40

回答

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类中处于正确的轨道。我看不到详细信息,但您也可能希望在remove()方法的签名中使用​​关键字来首先保护整个函数。然后,一旦你有了工作,使用更加紧密的目标块来减少必须单线程的代码量。

+0

感谢埃里克,这是一个错字,所以我修正了它,是的,基本上我想知道我的想法是否正确,因为我们需要使用相同的对象在线程上应用同步,并且在我提供的示例中,它实例化静态对象在构造函数中,所以它对我来说似乎是错误的,我认为它更好地在构造函数之前实例化。感谢本书的推荐,我也多次听说过,所以我必须开始阅读它才能理解所有多种可能性 – Uma 2015-04-03 16:04:22

+0

这不是一个静态构造函数。这是一个实例初始化块。它和构造函数会有相同的问题。顺便说一句,这不会编译,因为该字段是最终的。如果你的意思是一个*静态初始化块*,那么语法是'static {...}'。但它不是必需的。作为声明的一部分,您可以直接初始化静态变量。 – 2015-04-03 20:49:27

+0

谢谢@JBNizet,我在例子中清理了术语和代码。 – ericzundel 2015-04-04 22:25:18