2015-11-08 59 views
0

我有一個類Library這是一個第三方庫,我無法訪問源代碼。這個類在不同的班級我的項目中使用,如如何在Java中正確同步方法訪問

public class MyOwnClass1 { 
    private Library lib; 
    public void doTask() { 
     String res = lib.libMethod1(); 
     ... ... ... 
    } 
} 

然而,事實證明,該類Library不是線程安全,例如,當方法libMethod1在不同的線程同時調用它會導致奇怪的問題。因此,我必須實現我自己的線程安全機制,第一個是將Library變量封裝到另一個類中。

public class SafeLibrary { 
    private Library lib; 
    private Object mutex = new Object(); 
    ... ... ... 
    public String doTask() { 
     synchronized(this.mutex) { 
      return this.lib.libMethod1(); 
     } 
    } 
    ... ... ... 
} 

但正如我所說的,Library類用於不同類的不同方法。如果我必須將所有相關方法放入新的SafeLibrary類中,則會花費大量代碼修改。

所以這是第二個想法:

public class SafeLibrary { 
    private Library lib; 
    private Object mutex = new Object(); 
    public Object getMutex() { 
     return this.mutex; 
    } 
    public Library getLib() { 
     return this.lib; 
    } 
} 

然後我同步在我自己的類中的方法訪問:

public class MyOwnClass1 { 
    private SafeLibrary lib; 
    public void doTask() { 
     synchronized(lib.getMutext()) { 
      String res = lib.getLib().libMethod1(); 
      ... ... ... 
     } 
    } 
} 

通過使用第二方案,我只能做一些小的修改在相關的方法。但getMutex()似乎是一種不正確的方式。

我想知道哪種解決方案是正確的,或者是否有其他更好的解決方案?謝謝。

回答

1

如果庫,你要使用的方法不是最終的,與您共創庫對象自己(而不是從圖書館本身的靜態方法得到它),那麼你可以創建自己的類:

public class SynchronizedLibrary extends Library { 
    public synchronized String libMethod1() { 
     super.libMethod1(); 
    } 
} 

然後,您只需更換構造函數調用,甚至可以將聲明的類型保留爲普通舊庫(儘管您可能不想)。

1

你有兩個選擇,你可以同步你的類或同步特定的方法。你所做的是同步一個班級。這裏有一個同步的類實例: https://docs.oracle.com/javase/tutorial/essential/concurrency/syncrgb.html

這裏是同步的方法的一個例子: https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

基本上只是加上「同步」後的「公共」和返回​​值之前。把它想像爲爲方法添加「最終」。

最好的解決方案將取決於您的軟件架構。如果只是您擔心的一種方法,並且該方法是您正在創建的對象的特徵,那麼只需同步該方法即可。如果您正在創建其他對象/線程需要的獨立對象,請同步該對象。