[英]Keeping track of references in Java
在Java中,是否有任何方法可以判斷是否正在其他線程中(或通常在線程中)維護對對象的引用?
考慮以下類別:
public class ResourcePool<TYPE>
{
private final Queue<Object> emptyLocks = new LinkedBlockingQueue<>();
private final Queue<TYPE> available = new LinkedBlockingQueue<>();
private final Queue<TYPE> claimed = new LinkedBlockingQueue<>();
public void add(TYPE resource)
{
available.add(resource);
}
public TYPE claim() throws InterruptedException
{
if (available.isEmpty())
{
Object lock = new Object();
synchronized (lock)
{
emptyLocks.add(lock);
lock.wait();
}
}
TYPE resource = available.poll();
claimed.add(resource);
return resource;
}
public void release(TYPE resource)
{
if (!claimed.remove(resource)) return;
available.add(resource);
Object lock = emptyLocks.poll();
if (lock != null) synchronized (lock) {lock.notify();}
}
}
這里的想法是,多個線程可以聲明/釋放資源,以使兩個線程在任何給定時刻永遠不能擁有同一資源。 但是,如果線程忘記釋放資源,會發生什么? 更糟糕的是,如果線程調用release()然后繼續處理資源,該怎么辦?
使用WeakReference類,可以判斷何時不再存在對給定對象的強引用。 但是,發生這種情況時,該對象將被垃圾回收,並且不見了。 SoftReference可能會起作用,但是在將資源重新放入“可用”列表之前,仍有機會對我們的資源進行GC處理。
因此,這里的問題是 : 有沒有辦法跟蹤這些資源是否仍在實際使用中?
理想情況下,線程可以聲明()資源,並在需要時使用它們,並且一旦不再維護引用,這些資源將自動釋放。 我認為這將非常優雅,並且在其他情況下也很有用。
答案很簡單:否
GC在VM全局級別工作,並且在當前實施中(至少在Hotspot中),它不使用引用計數,更不用說引用跟蹤。 這意味着即使VM也不總是知道任意時間點所引用的內容。
通常,GC還是錯誤的工具,無法跟蹤需要及時發布的內容。 GC可能很少運行(在極端情況下,GC可能會調整為每隔幾個小時運行一次)。 您可能希望自己的資源在擁有塊作用域結束后立即可用於其他線程。 這個要求與GC處理不嚴的要求大不相同。
您想要的是立即檢測每個線程超出范圍的情況。 雖然這是一個不錯的功能,但問題是,這樣做是否值得付出代價的性能影響。
資源的示例以及在釋放后釋放/保留資源的線程“遺忘”的情況可以按照慣例處理:使用try-finally或濫用try-with-resources塊以確保生命周期是正確維護。
為了捕獲資源的意外泄漏,您可以濫用finalize; 但是, 當資源完成時 ,它也不是可預測的(而且您只能進行清理,不應完成資源的復活;有關完成此操作,請參見JLS)。
編輯:您可以輕松地抵御利用資源釋放后 stroing在資源所有者胭脂線程。 然后,資源可以執行運行時檢查,以確保調用線程確實是當前所有者。
您正在搜索finalize()方法。 當無法再訪問對象時,必須重寫此方法以進行清理。
請注意 ,創建finalize()方法並不像看起來那樣簡單(如這些答案所述 )。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.