Cuando un objeto cambia su estado de accesibilidad, se puede colocar una referencia al objeto en una cola de referencia. El recolector de basura utiliza estas colas para comunicarse con nuestro código sobre los cambios en la accesibilidad de los objetos. Estas colas son la mejor manera de detectar cambios de accesibilidad, aunque también podemos detectar los cambios de accesibilidad del objeto verificando si el valor de retorno del método GET es nulo.
Los objetos de referencia pueden asociarse con colas específicas cuando se construyen. Cada subclase de referencia proporciona constructores de la siguiente forma:
. referencia de fuerza pública (T referencia, referenceQueueq): este método crea un nuevo objeto de referencia con el objeto de referencia dado y registra el objeto de referencia a la cola dada. Las referencias débiles y las referencias suaves se insertan en la cola después de que el recolector de basura determina que sus objetos de referencia ingresan al estado de acachabilidad específico que representan, y ambas referencias se borrarán antes de la cola de inserción. Las referencias virtuales también se insertarán en la cola después de que el recolector de basura determine que sus objetos de referencia han ingresado al estado accesible virtual, pero no se borrarán. Una vez que el objeto de referencia es insertado en la cola por la colección de basura, el valor de retorno de su método GET definitivamente será nulo, por lo que el objeto nunca puede resucitarse.
Registrar un objeto de referencia en una cola de referencia no crea una referencia entre la cola y el objeto de referencia. Si nuestro objeto de referencia en sí mismo se vuelve inalcanzable, no se puede insertar en la cola. Por lo tanto, nuestra aplicación debe mantener una fuerte referencia a todos los objetos referenciados.
La clase ReferenceQueue proporciona tres métodos para eliminar las referencias en una cola:
El método de la encuesta permite que un hilo consulte si una referencia está en una cola y realiza una acción específica cuando la referencia existe en la cola. El método eliminar puede manejar situaciones más complejas (menos comunes), donde un hilo dedicado es responsable de eliminar las referencias de la cola y realizar acciones apropiadas. El comportamiento de bloqueo de estos métodos es el mismo que el comportamiento de bloqueo definido en object.lait. Para una referencia específica, podemos consultar si está en la cola por su método de isenqueada, o forzarla a la cola llamando a su método de enqueue, pero generalmente este tipo de tapón lo realiza el recolector de basura.
Las referencias virtuales en la cola de referencia se pueden usar para determinar cuándo se puede reciclar un objeto. No podemos acceder a ningún objeto a través de referencias virtuales, incluso si el objeto es accesible de otras maneras, porque el método GET de referencia virtual siempre devuelve nulo. De hecho, el uso de referencias virtuales para encontrar el objeto que se recicla es la forma más segura, ya que las referencias débiles y las referencias suaves se insertarán en la cola después de que el objeto se pueda terminar, mientras que las referencias virtuales se insertan en la cola después de que se termina el objeto de terminación, es decir, la cola, la cola se inserta después del último momento en que el objeto puede realizar ciertas operaciones, por lo que es absolutamente seguro. Si puede, siempre se deben usar referencias virtuales, porque otras referencias tendrán la posibilidad de que finalice los métodos usen objetos endables.
Considere un ejemplo de un administrador de recursos que puede controlar el acceso a colecciones de recursos externas. Los objetos pueden solicitar acceso a un recurso externo y no finalizar el acceso hasta que se complete la operación, después de lo cual deben devolver el recurso utilizado al Administrador de recursos. Si este recurso se comparte, sus derechos de uso se pasarán entre múltiples objetos e incluso se puede aprobar entre múltiples hilos, por lo que es difícil para nosotros determinar qué objeto es el último usuario de este recurso y, por lo tanto, es difícil determinar qué código de código será responsable de devolver este recurso. Para manejar esta situación, el gerente de recursos puede lograr un reciclaje automático de este recurso al asociar un recurso a un objeto especial llamado clave. Mientras el objeto clave sea accesible, creemos que este recurso todavía está en uso; Mientras el objeto clave se pueda recolectar como basura, el recurso se liberará automáticamente. El siguiente código es una representación abstracta de los recursos anteriores:
Interface Resource {void use (clave de objeto, objeto ... args); Void Release (); }Cuando se obtiene un recurso, su objeto clave debe proporcionarse al Administrador de recursos. Para una instancia de recurso devuelto, este recurso solo se puede usar si obtiene su clave correspondiente. Esto asegura que después de reciclar la clave, su recurso correspondiente ya no se puede usar, incluso si el objeto de recursos que representa este recurso aún puede ser accesible. Tenga en cuenta que el objeto de recursos no almacena una fuerte referencia al objeto clave, lo cual es importante porque esto evita que el objeto clave se vuelva inalcanzable, lo que resulta en que el recurso sea innumerable. La implementación de recursos puede anidarse en el administrador de recursos:
Clase estática privada ResourceImpl implementa recursos {int keyhash; Boolean NeedsRelease = False ResourceImpl (clave de objeto) {keyHash = System.IdentityHashCode (Key); // = Configurar el recurso externo NeedsRelease = true; } public void use(Object key, Object... args){ if (System.identityHashCode(key)!=keyHash) throw new IlleqalArgumentException("wrong key" //...use the resource } public synchronized void release(){ if (needsRelease){ needsRelease=false://=release the resource } } }El código hash del objeto clave se almacena cuando se crea el recurso, y cada vez que se llama al método de uso, verifica si se proporciona la misma clave. El uso real de los recursos también puede requerir sincronización, pero por simplicidad, los omitimos aquí. El método de lanzamiento es responsable de liberar el recurso. El usuario de recursos puede llamarlo directamente después del uso, o por el administrador de recursos cuando ya no se hace referencia al objeto clave. Dado que usaremos subprocesos independientes para monitorear la cola de referencia, el método de liberación debe sincronizarse y se deben permitir múltiples llamadas.
El administrador de recursos real tiene el siguiente formulario:
Public Final Class ResourceManager {Refective FinalQueue
El objeto clave puede ser cualquier objeto, lo que brinda a los usuarios de recursos una gran flexibilidad en comparación con que el Administrador de recursos asigne objetos clave. Cuando se llame al método GetResource, se creará un nuevo objeto MPL de trabajo de recursos, y la clave proporcionada al método se pasará al nuevo objeto RecurseImpl. Luego se crea una referencia virtual, y su objeto referencial es la clave pasada al método, y luego esta referencia virtual se insertará en la cola de referencia del Administrador de recursos. Los objetos de referencia y referencia virtuales creados al final se almacenarán en la tabla de mapeo. Esta tabla de mapeo tiene dos propósitos: uno es mantener todos los objetos de referencia virtuales accesibles, y la otra es proporcionar una forma conveniente de consultar el objeto de recurso real asociado con cada referencia virtual. (Una alternativa es subclase Phantomreference y almacenar el objeto de recursos en un campo).
Si el objeto clave se vuelve inalcanzable, el administrador de recursos utiliza un hilo "Reaper" separado para procesar el recurso. El método de cierre "cierre" al explorador terminando el hilo de la cosechadora (en respuesta a una interrupción), lo que hace que el método GetResource arroje una excepción ILLE-LLLESTATEException. En este diseño simple, no se procesarán las referencias que conecten una cola después de que el Explorer esté cerrado. El hilo real de la cosechadora es el siguiente:
Class ReaperThread extiende el hilo {public void run () {// ejecutar hasta que se interrumpa mientras (true) {try {reference ref = queue.remove (); Recursos res = nulo; Synchronized (ResourceManager.THIS) {res = refs.get (ref); Refs. eliminar (ref); } res .release (); ref.clar (); } catch (interruptedException ex) {break; // Todo hecho}}}}ReaperThread es una clase interna, y el hilo de la cosechadora dado se ejecutará hasta que el administrador de recursos asociado con él esté cerrado. El subproceso bloquea el método eliminar hasta que la referencia virtual asociada con una clave específica se inserta en la cola de referencia. Esta referencia virtual puede obtener una referencia al objeto de recurso de la tabla de mapeo, y luego este par de "clave a referencia" se eliminará de la tabla de mapeo. Inmediatamente después, su método de lanzamiento se solicita en el objeto de recurso para liberar el recurso. por fin,
La referencia virtual se borra para que la clave se pueda reciclar.
Como alternativa al uso de subprocesos independientes, cualquier operación que llame al método de la encuesta en la cola de referencia y libera todos los recursos cuyas claves se han vuelto inalcanzables pueden ser reemplazadas por el método GetResource ", y el método ShutDow" también puede usarse para realizar la operación de encuesta final. La semántica del administrador de recursos dependerá del tipo de recurso real y el patrón de uso de recursos.
Los diseños que utilizan colas de referencia son mucho más confiables que los diseños que usan terminaciones directamente (especialmente referencias virtuales). Pero debemos recordar que la hora y ubicación exacta del objeto de referencia insertado en la cola de referencia no es seguro, ni estamos seguros de si todas las referencias conectables se han insertado en la cola de referencia cuando la aplicación termina. Si necesitamos asegurarnos de que todos los recursos se puedan liberar antes de que termine la aplicación, debemos instalar el gancho de cierre necesario o usar otros protocolos definidos por la aplicación para garantizar que esto se logre.