2015-04-03 116 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