Analysis of reference queue related principles for managing resources in Java _java

Source: Internet
Author: User
Tags static class

When an object changes its accessibility state, a reference to that object may be placed in the reference queue (reference queue). These queues are used by the garbage collector to communicate with our code about the changes in the object's accessibility. These queues are the best way to detect accessibility changes, although we can also detect the accessibility changes of an object by examining whether the return value of the Get method is null.

Reference objects can be associated with a specific queue at construction time. Each subclass of reference provides the following form of constructor:

. Public strength Reference (T referent, Referencequeueq): This method creates a new reference object with the given reference object and registers the referenced object with the given queue. Weak references and soft references are inserted into the queue after the garbage collector determines that their alleged objects are in the specific accessibility state they represent, and both references are cleared before the docking queue. A virtual reference is inserted into the queue after the garbage collector determines that its alleged object enters the virtual state, but they are not purged. Once a referenced object is inserted into the queue by the garbage collector, the return value of its Get method is bound to be null, so the object cannot be resurrected again.

Registering a Reference object in a reference queue does not create a reference between the queue and the referenced object. If our reference object itself becomes unreachable, then it cannot be inserted into the queue. So our application needs to keep a strong reference to all the referenced objects.

The Referencequeue class provides three methods for removing references in queues:

    1. . public Reference <? Extends under >poll (): To remove and return the next referenced object in the queue, or null if the queue is empty.
    2. . Public Referenceremove () throws Interruptedexception: Used to remove and return the next referenced object in the queue, which blocks until the queue returns the available Reference object.
    3. . Public Referenceremove (long timeout) throws Interrupte-dexception: Used to remove and return the next referenced object in the queue. This method blocks until the queue returns the available reference object, or ends after the specified timeout is exceeded. Returns NULL if the specified timeout is exceeded. Specifying a timeout of 0 means waiting indefinitely.

The poll method allows a thread to query whether a reference is in the queue and perform a specific action when the reference exists in the queue. The Remove method can handle more complex (and rarer) cases where a dedicated thread is responsible for removing the reference from the queue and performing the appropriate action. The blocking behavior of these methods is the same as the blocking behavior defined in object.wait. For a particular reference, we can query whether it is in the queue by its Isenqueued method, or force it into the queue by calling its Enqueue method, but this is usually done by the garbage collector.

A virtual reference in a reference queue can be used to determine when an object can be reclaimed. We cannot access any object through a virtual reference, this is true even if the object is accessible in other ways, because the virtual reference's Get method always returns null, and in fact it is the safest way to find objects to be reclaimed with a virtual reference, because weak references and soft references are inserted into the queue after the object can be terminated. A virtual reference is an absolute security when the alleged object is inserted into the queue after it is terminated, that is, after the last time the object can perform certain operations. If you can, you should always use a virtual reference, because other references will have the possibility that the Finalize method uses the object that can be terminated.

Consider an example of a resource manager that controls access to external resource collections. objects can request access to an external resource and end access until the operation completes, after which they should return the resources they use to the resource manager. If this resource is shared, its use is passed between multiple objects, and may even be passed between threads, so it is difficult to determine which object is the last user of the resource, making it difficult to determine which code will be responsible for returning the resource. To handle this situation, the resource manager can automate the collection of resources by associating the resource with a special object called a key. As long as the key object is accessible, we assume that the resource is still in use, and that the resource is automatically freed as long as the key object can be garbage collected. The following code is an abstract representation of the above resources:

Interface resource{

void use (Object key, Object...args);

void release ();

}

When a resource is obtained, its key object must be provided to the resource manager. For a returned resource instance, this resource can only be used if it obtains its corresponding key. This ensures that after the key is reclaimed, its corresponding resource is no longer available, even if the resource object representing the resource itself may still be up to date. Note that it is important that the resource object does not store a strong reference to the key object, because this prevents the key object from becoming unreachable, causing the resource to not be retracted. Resource implementations can be nested within the resource manager:

private static class Resourceimpl implements resource{

int keyhash;

Boolean needsrelease=false

Resourceimpl (Object key) {

keyhash=system.identityhashcode (key);

=set up the external resource

needsrelease=true;}

public void use (Object key,object ... args) {

if (System.identityhashcode (key)!=keyhash)

throw new Illeqalargum Entexception ("Wrong key"

//...use the Resource

} public

synchronized void release () {

if needs Release) {

needsrelease=false:

//=release the Resource

}

}

}

The hash code of the key object is stored when the resource is created, and whenever the use method is invoked, it checks to see if the same key is provided. The actual use of resources may also need to be synchronized, but for the sake of simplicity, we omit them here. The release method is responsible for releasing the resource, which can be called directly by the user of the resource after the end of the use, or by the resource manager when the key object is no longer referenced. Because we will use separate threads to monitor the reference queue, the release method must be synchronized and must allow multiple invocations.

The actual resource manager has the following form:

Public final class resourcemanager{

final Referencequeue


A key object can be any object, which gives the resource user a great deal of flexibility compared to having the resource manager assign a key object. When the GetResource method is invoked, a new resource Mpl object is created, and the key provided to the method is passed to the new Resourceimpl object. A virtual reference is then created, and the reference object is the key passed to the method, which is then inserted into the resource Manager's reference queue. The last virtual reference and reference object that was created are stored in the mapping table, which has two uses: one is to keep all the virtual reference objects up to date, and the second is to provide a convenient way to query the actual resource object associated with each virtual reference. (Another way is to subclass phantomreference and place the resource object in a field.) )

If the key object becomes unreachable, the resource manager uses a separate "harvester" (Reaper) thread to handle the resource. The Shutdown method closes the resource manager by terminating the harvester thread (in response to a break), causing the GetResource method to throw a Ille-lllestateexception exception. In this simple design, any references to the docking queue after the resource manager is closed are not processed. The actual harvester threads are as follows:

Class Reaperthread extends thread{public

void Run () {

//run until interrupted while

(true) {

try{
    Reference ref=queue.remove ();

Resource Res=null;

Synchronized (resourcemanager.this) {

res=refs.get (ref);

Refs.  Remove (ref);

Res. Release ();

Ref.clear ();

catch (Interruptedexception ex) {

break;//all done

}}}



The Reaperthread is an inner class, and the given Harvester thread runs until its associated resource manager closes. The thread blocks on the Remove method until the virtual reference associated with a particular key is inserted into the reference queue. This virtual reference can get a reference to the resource object from the mapping table, and then the key-one reference pair will be removed from the mapping table. Immediately thereafter, the release method is invoked on the resource object to free the resource. At last

The virtual reference is cleared so that the key can be reclaimed.

As an alternative to using a stand-alone thread, it is possible to invoke the poll method on a reference queue and release all resources whose keys have become unreachable by Getresourc "method, Shutdow" method can also be used to perform the last poll operation. The semantics of the resource manager will depend on the actual resource type and the pattern of resource usage.

The design of the

Using a reference queue is much more reliable than a design that uses an end directly, especially when using a virtual reference. But we have to remember that the exact time and location of the referenced object being inserted into the reference queue is uncertain and we are not sure that all pluggable references are dagger to the reference queue at the end of the application. If we need to make sure that all resources are freed before the application terminates, you must install the necessary shutdown hooks or use other protocols defined by the application to ensure that this is achieved.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.