객체가 도달 가능성 상태를 변경하면 객체에 대한 참조가 참조 큐에 배치 될 수 있습니다. 이 대기열은 쓰레기 수집기가 객체 접근성의 변경 사항에 대한 코드와 통신하는 데 사용됩니다. 이러한 대기열은 접근성 변경을 감지하는 가장 좋은 방법이지만 Get 메소드의 반환 값이 Null인지 확인하여 객체의 접근성 변경을 감지 할 수도 있습니다.
기준 객체는 구성시 특정 대기열과 연관 될 수 있습니다. 기준의 각 서브 클래스는 다음 형식의 생성자를 제공합니다.
.public 강도 참조 (t reference, referencequeueq) :이 메소드는 주어진 참조 객체와 함께 새로운 참조 객체를 생성하고 주어진 큐에 참조 객체를 등록합니다. 쓰레기 수집기가 참조 객체가 그들이 나타내는 특정 도달 가능성 상태에 들어가고 삽입 대기열 전에 두 참조가 지워진 후 약한 참조 및 소프트 참조가 대기열에 삽입됩니다. 쓰레기 수집기가 참조 객체가 가상 도달 상태에 입력했다고 판단한 후 가상 참조는 대기열에 삽입 될 것입니다. 쓰레기 수집기가 기준 객체를 큐에 삽입하면 Get 메소드의 리턴 값은 확실히 널이므로 객체를 부활 할 수 없습니다.
참조 객체를 참조 큐에 등록하면 큐와 참조 객체 사이에 참조가 생기지 않습니다. 참조 객체 자체가 도달 할 수 없게되면 대기열에 삽입 할 수 없습니다. 따라서 우리의 응용 프로그램은 모든 참조 된 객체에 대한 강력한 참조를 유지해야합니다.
ReferenceQueue 클래스는 큐에서 참조를 제거하는 세 가지 방법을 제공합니다.
설문 조사 방법을 사용하면 참조가 큐에 있는지 여부를 쿼리하고 큐에 참조가 존재할 때 특정 작업을 수행 할 수 있습니다. 제거 방법은 전용 스레드가 큐에서 참조를 제거하고 적절한 작업을 수행하는 데 도움이되는보다 복잡한 (덜 일반적인) 상황을 처리 할 수 있습니다. 이 방법의 차단 동작은 Object.Wait에 정의 된 차단 동작과 동일합니다. 특정 참조를 위해, 우리는 isenqueued 방법으로 대기열에 있는지 여부를 쿼리하거나 Enqueue 메소드를 호출하여 대기열에 강제로 강제 할 수 있지만 일반적으로 이런 종류의 플러그는 쓰레기 수집기에 의해 수행됩니다.
참조 큐의 가상 참조는 객체를 재활용 할 수있는시기를 결정하는 데 사용될 수 있습니다. 가상 참조의 get 메소드가 항상 null을 반환하기 때문에 다른 방식으로 객체에 도달 할 수있는 경우에도 가상 참조를 통해 객체에 액세스 할 수 없습니다. 사실, 가상 참조를 사용하여 재활용 할 객체를 찾는 것이 가장 안전한 방법입니다. 약한 참조와 소프트 참조가 객체를 종료 한 후 큐에 삽입되기 때문에, 객체가 종료 된 후에 큐가 삽입 된 후에 가상 참조가 큐에 삽입되기 때문입니다. 가능하다면 가상 참조는 항상 사용해야합니다. 다른 참조에는 최종 객체를 사용하는 방법을 마무리 할 가능성이 있기 때문입니다.
외부 리소스 컬렉션에 대한 액세스를 제어 할 수있는 리소스 관리자의 예를 고려하십시오. 객체는 외부 리소스에 대한 액세스를 요청할 수 있으며 작업이 완료 될 때까지 액세스를 종료하지 않으며, 그 후에는 리소스 관리자에게 사용 된 리소스를 반환해야합니다. 이 리소스가 공유되면 여러 객체간에 사용 권한이 전달되고 여러 스레드간에 전달 될 수 있으므로이 리소스의 마지막 사용자인지 판단하기가 어려워서이 리소스를 반환 할 수있는 코드 조각을 결정하기가 어렵습니다. 이러한 상황을 처리하기 위해 리소스 관리자는 리소스를 키라는 특수 객체와 연결 하여이 리소스의 자동 재활용을 달성 할 수 있습니다. 핵심 객체에 도달 할 수있는 한, 우리는이 리소스가 여전히 사용되고 있다고 생각합니다. 핵심 객체를 쓰레기로 수집 할 수있는 한 자원은 자동으로 해제됩니다. 다음 코드는 위의 리소스의 추상적 인 표현입니다.
인터페이스 자원 {void use (개체 키, 개체… args); void release (); }리소스가 얻어지면 자원 관리자에게 핵심 개체를 제공해야합니다. 반환 된 리소스 인스턴스의 경우이 리소스는 해당 키를 얻는 경우에만 사용할 수 있습니다. 이를 통해 키를 재활용 한 후이 리소스를 나타내는 리소스 개체에 여전히 액세스 할 수있는 경우에도 해당 리소스를 더 이상 사용할 수 없습니다. 리소스 객체는 핵심 객체에 대한 강력한 참조를 저장하지 않으며, 이는 핵심 객체가 도달 할 수 없게되므로 리소스가 부적절하지 않기 때문에 중요합니다. 리소스 구현은 리소스 관리자에 중첩 될 수 있습니다.
개인 정적 클래스 리소스 이먼은 리소스 {int keyhash; 부울 NeedsRelease = false resourceimpl (개체 키) {keyhash = System.InditityHashCode (키); // = 외부 리소스 설정 NeedSelease = true; } public void use (객체 키, 객체 ... args) {if (system.identityHashCode (key)! = keyhash) 던지기 새로운 endeqalargumentException ( "잘못된 키"//..키 객체의 해시 코드는 자원이 생성 될 때 저장되며 사용 방법이 호출 될 때마다 동일한 키가 제공되는지 확인합니다. 실제 리소스 사용에는 동기화가 필요할 수도 있지만 단순화를 위해 여기에서 생략합니다. 릴리스 방법은 리소스를 공개 할 책임이 있습니다. 사용 후 리소스 사용자 또는 키 객체가 더 이상 참조되지 않은 경우 리소스 관리자가 직접 호출 할 수 있습니다. 독립 스레드를 사용하여 참조 큐를 모니터링하기 때문에 릴리스 방법은 동기화되어야하며 여러 통화가 허용되어야합니다.
실제 자원 관리자는 다음과 같은 형식을 가지고 있습니다.
공개 최종 클래스 ResourcEmanager {Final ReferenceQueue
핵심 객체는 모든 객체 일 수 있으며, 이는 리소스 관리자에게 리소스 관리자가 키 객체를 할당하도록하는 것과 비교하여 리소스 사용자에게 큰 유연성을 제공합니다. getResource 메소드가 호출되면 새로운 리소스 작업 MPL 객체가 생성되고 메소드에 제공된 키가 새로운 ResourceImpl 객체로 전달됩니다. 그런 다음 가상 참조가 생성되고 참조 객체가 메소드로 전달 된 키 이며이 가상 참조는 Resource Manager의 참조 큐에 삽입됩니다. 마지막에 생성 된 가상 참조 및 참조 객체는 매핑 테이블에 저장됩니다. 이 매핑 테이블에는 두 가지 목적이 있습니다. 하나는 모든 가상 참조 객체에 도달 할 수 있도록하고 다른 하나는 각 가상 참조와 관련된 실제 자원 객체를 쿼리하는 편리한 방법을 제공하는 것입니다. (대안은 공상 대상 회의를 서브 클래스를하고 리소스 객체를 필드에 저장하는 것입니다.)
키 객체에 도달 할 수 없게되면 리소스 관리자는 별도의 "리퍼"스레드를 사용하여 리소스를 처리합니다. 차단 메소드는 수확기 스레드 (인터럽트에 대한 응답)를 종료하여 탐색기를 "닫기"하여 getResource 메소드가 ille-lllestateException 예외를 던지게합니다. 이 간단한 디자인에서는 탐색기가 닫힌 후 큐를 연결하는 참조가 처리되지 않습니다. 실제 수확기 실은 다음과 같습니다.
Class ReperThread는 스레드 {public void run () {// 중단 될 때까지 실행됩니다 (true) {try {reference ref = queue.remove (); 자원 res = null; 동기화 된 (resourcemanager.this) {res = refs.get (ref); 참조. 제거 (ref); } res .release (); ref.clear (); } catch (InterruptedException ex) {break; // all dod}}}}Reperthread는 내부 클래스이며 주어진 수확기 스레드는 관련 리소스 관리자가 닫힐 때까지 실행됩니다. 스레드는 특정 키와 관련된 가상 참조가 참조 큐에 삽입 될 때까지 제거 메소드의 블록 블록입니다. 이 가상 참조는 매핑 테이블에서 자원 객체에 대한 참조를 얻을 수 있으며,이 "키와 참조"쌍이 매핑 테이블에서 제거됩니다. 그 후 즉시, 자원 객체에서 릴리스 방법이 자원을 해제하기 위해 호출됩니다. 마침내,
키를 재활용 할 수 있도록 가상 참조가 지워집니다.
독립적 인 스레드를 사용하는 대안으로, 참조 큐에서 폴링 메소드를 호출하고 키를 처리 할 수없는 모든 리소스를 getResource "메소드로 대체 할 수 있으며 Shutdow"방법을 사용하여 최종 폴링 작업을 수행 할 수 있습니다. 리소스 관리자의 의미는 실제 리소스 유형 및 리소스 사용 패턴에 따라 다릅니다.
참조 큐를 사용하는 설계는 종단을 직접 사용하는 설계 (특히 가상 참조)보다 훨씬 신뢰할 수 있습니다. 그러나 참조 대기열에 삽입 된 기준 객체의 정확한 시간과 위치는 확실하지 않으며 응용 프로그램이 끝날 때 모든 플러그 가능한 참조가 참조 큐에 삽입되었는지 확실하지 않다는 것을 기억해야합니다. 응용 프로그램이 종료되기 전에 모든 리소스를 해제 할 수 있는지 확인 해야하는 경우, 필요한 종료 후크를 설치하거나 응용 프로그램에서 정의한 다른 프로토콜을 사용하여이를 달성해야합니다.