2014-12-07 3 views
0

l:Map<Long,Foo> 개의 foo 객체가 있습니다. 그리고 내 응용 프로그램 컨텍스트에서 Foo의 인스턴스를 너무 많이 생성하고 일부 인스턴스가 둘 이상의 스레드 스택과 공유됩니다.
Foo 클래스 다음참조가있는 준비되지 않은 객체에 대해 참조가있는 객체 표시

class Foo{ 
public long id; 
public AtomicInteger ins; 
public Foo(long d,AtomicInteger i){id=d;ins=i;} 
public Foo(long d){id=d;ins=new AtomicInteger(1);} 
} 
//-- 
class Bar{ 
Foo friend; 
public Bar(Foo f){friend=f;} 
//....some other properties 
} 

Foo

public synchronized Bar a_bar_please(long id){ 
Foo f=l.get(id);//no null allowed, Map implementation doesn't allow it 
if(f==null){f=new Foo();l.put(id,f);} 
else{f.ins.incrementAndGet();} 
return new Bar(f); 
} 

을 얻는 방법입니다 그리고 여기 (GC 준비)

public synchronized void a_gone_bar(Bar b){ 
if(b.friend.decrementAndget()==0){l.remove(b.friend.id);} 
} 

내가 제거 막대를 제거하는 방법 어떤 Bar 인스턴스가없는 경우 Foo 인스턴스 모든 것이 정상적으로 처리되면 현재 상황에 문제가 없습니다.


사례 연구 :
지금 10 개 스레드 ID 1 a_bar_please(id:long):Bar 방법을 요구 가정, 그래서 인스턴스의 모든 friend field와 공유 Foo 인스턴스 참조가 10 개의 새로운 Bar 객체를 의미한다.
여기에서 Foo 인스턴스는 Bar 인스턴스에서 10 개이고 컨텍스트 l:Map에서 하나 인 11 개의 참조가 있습니다.
이제 Foo 인스턴스를 개봉 Bar 인스턴스가 연결되어 있지 않은 경우 l 맵에서 제거하고 싶습니다.
Bar을 들고 스레드 (8)을 고려 플러스 ins의 최소 수는 8 것이기 때문에 상황이 Foo 개체를 개최하고, 문맥 GC 마킹을 위해 그것을 제거하지 않습니다 그래서, a_gone_bar(b:Bar):void를 호출하지 않는 friend:Foo 객체를 공유합니다.
지도에서 참조가있을 때 Foo 인스턴스를 어떻게 표시 할 수 있습니까?

답변

0

WeakRefernece 클래스를 확인하십시오. 그 소리가 당신이 원하는 것입니다. 간단히 말해 foo이 아닌 new WeakReference(foo)을 컨텍스트에 저장하고 이에 따라 .get을 수정하십시오 (ref = context.get(id); foo = ref == null ? null : ref.get). .enqueue 메서드를 재정의하여 컨텍스트에서 항목이 수집되면 항목을 제거 할 수도 있습니다.

기본적으로 GC는 약하게 참조되는 미사용 개체를 고려하고 다음주기 중에 개체를 수집합니다.

이렇게하면 참조 카운팅 (a_gone_bar())의 필요성이 없어 지므로 GC가 컨텍스트에서 막대를 제거하는 데주의를 기울입니다.

관련 문제