静态变量,线程和构造函数Java

时间:2015-04-03 15:39:14

标签: java multithreading variables static

我从一本公认的样本书中看到了这一点,所以很难回答那些我不理解的东西。

  

一个名为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作为静态服务并不在synchronizeRandomAccessFile用于DataflightsService,因为每次都是FlightFileAccess每个DataflightsService实例在随机访问文件上做他们的事情忽略同步。 而不是在静态启动器中实例化DataflightsService。我是对的吗?

我希望尽可能多的解释提供能够根据需要多次实例化DataflightsService的最佳方法(假设想象每个客户端都有自己的{{1}}实例)并且之后能够在文件上进行同步以进行删除,例如,以便几个客户端不会访问该文件。对不起,我需要为每个客户提供一个{{1}},但没有cookie。

1 个答案:

答案 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 {...}块来减少必须单线程的代码量。