2016-07-29 22 views
12

一般來說,我一直看到的try-與資源用於分配新對象實例close()方法被調用,因爲它超出的範圍外。正在使用try-with-resources而沒有新的對象實例壞形式?

據我所知,創建一個新對象不是必需的,try-with-resources語法只需要一個局部變量在超出範圍時調用close()。因此,您可以使用它來控制「配對操作」,例如從池中分配某些內容並確保其返回。

例如,下面MyHandle展示瞭如何釋放池實例,當你不再需要它:

// init 
class MyHandle implements AutoCloseable { 
    boolean inUse = false; 
    public MyHandle allocate() { 
     inUse = true; 
     return this; 
    } 

    public void close() { 
     inUse = false; 
    } 
} 

MyHandle[] pool = new MyHandle[POOL_SIZE]; 
for (int i = 0; i < pool.length; i++) { 
    pool[i] = new MyHandle(i); 
} 

// allocate 
MyHandle allocateFromPool() { 
    for (int i = 0; i < pool.length; i++) { 
     if (!pool[i].inUse) 
      return pool[i].allocate(); 
    } 
    throw new Exception("pool depleted"); 
} 

// using resources from the pool 

try (MyHandle handle = allocateFromPool()) { 
    // do something 
} 
// at this point, inUse==false for that handle... 

這被認爲是不好的形式?

編輯:我想我問是否有更好的替代方案來構建這種邏輯,或者如果使用上述方法時有一些主要缺點。我發現在庫中使用它可以創建一個乾淨的API。

編輯2:請忽略代碼示例中的問題,我在SO文本框中將其內聯編寫,以便使我的問題在某些示例中得到明確。顯然這不是真正的代碼! :)

+5

這很好 - 這也是它在使用連接池時的一般做法:'try(Connection c = pool_or_datasource.getConnection()){}'... – assylias

回答

10

嘗試與資源語法的目的是作爲一種語法加糖,以確保您處置一個對象,無論處理邏輯如何。在你的情況下,它將對象返回到池中。像這樣使用try-with-resource絕對沒有錯。它可能不是最常見的用例,但它絕對是一個有效的用例。

4

在封面之下,大多數資源(例如文件描述符)都是由操作系統從池中有效分配的,然後在關閉時返回到池中。

以這種方式使用try-with-resources是完全有效的。

N.B.儘管你的代碼示例有重要的線程問題,但爲了清晰起見,我認爲必要的線程安全性已被刪除。我提到它只是因爲人們不應該複製你的代碼並在實現中使用它。

2

這樣的資源嘗試沒有錯。但在你的情況下,我會擔心重新使用已經從另一個線程重新打開的關閉句柄的商業機密重用。

有點間接會解決這個問題,返回MyHandleWrapper而不是直接訪問MyHandle(allocateFromPool將返回一個MyHandleWrapper的新實例)。它不會解決所有其他線程問題。

public class MyHandleWrapper extends MyHandle { 
    private MyHandle handle; 
    private boolean closed; 

    public void close() { 
     if(!closed){ 
      handle.inUse = false; 
     } 
     closed = true; 
    } 

    public void read() { 
     if (closed) { 
      throw new IllegalStateException("Already closed"); 
     } 
     handle.read(); 
    } 
} 

基本上,如果句柄在MyHandleWrapper中關閉,則保留該信息。你必須保護任何狀態改變對該標誌的訪問handle,如果有必要的話拋出適當的例外。

相關問題