Building a cache of sensitive data using soft references

Building a cache of sensitive data using soft references


1. Implementation principle

1. Application scenario Data with high
query frequency; each query needs to interact with the database through the interface, and the construction of the object still needs to occupy a part of the memory; even if the result of the last query is still in the memory and has not been reclaimed by the GC but It is still necessary to perform the same query operation again;
put the query results into memory - occupy a large amount of memory space, increasing the possibility of memory overflow;
re-query every time - after the current query results are used, the defect of the implementation is that even if garbage The collection thread has not yet performed garbage collection, and the object containing the employee file information is still intact in memory, and the application has to
rebuild . Reduce unnecessary access and greatly improve the running speed of the program

2. Features
of soft references For objects associated with soft references, if the memory is sufficient, the garbage collector will not reclaim the object, and if the memory is not enough, these objects will be reclaimed

3. Soft references with reference queues
Soft references can be used to implement memory -sensitive caches. Soft references can be used in conjunction with a reference queue (ReferenceQueue). If the object referenced by the soft reference is reclaimed by the garbage collector, the Java virtual machine will add the soft reference to the associated reference queue.

2. Code realization

realization idea
  • The tool class uses the singleton implementation of the lazy mode to avoid problems in multi-threaded calls, and the external interface is modified with the synchronized keyword
  • Build a cache, use Hashtable, key: the unique identifier of the stored content, value: the soft reference implementation of the stored object; when fetching an element, if the cache exists, it means that the object has not been reclaimed at this time, or has been reclaimed, but the soft reference is Not cleared in the reference queue; if not, the stored object has been GCed;
  • Build a soft reference queue. The generic T is the object to be stored. When the object on which the soft reference depends is reclaimed by the GC, the JVM adds the soft reference to the reference queue associated with it. That is, at this time, the memory occupied at this time is reclaimed before waiting for the GC to reach the out of memory, so each time a new object is placed, it is first judged whether the queue has a value, and if so, the occupied memory space is actively released.



/**
 * Employee information class
 */
public class Employee {
	
	private String id ; // 主键

	private String name ; // 姓名
	
	private String department ; // department
	
	private Double salary ; // 工资

	public Employee(String id){
		this.id = id ;
	}
	
	public Employee(String id, String name, String department, Double salary) {
		super();
		this.id = id;
		this.name = name;
		this.department = department;
		this.salary = salary;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getDepartment() {
		return department;
	}

	public void setDepartment(String department) {
		this.department = department;
	}

	public Double getSalary() {
		return salary;
	}

	public void setSalary(Double salary) {
		this.salary = salary;
	}

	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", department="
				+ department + ", salary=" + salary + "]";
	}
}






import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.Hashtable;

/**
 * Employee information cache
 */
public class EmployeeCache {

	// Singleton pattern: lazy man
	private static EmployeeCache employeeCache ;
	
	private EmployeeCache(){
		// When constructing a cache object, initialize the cache container and soft index queue
		cache = new Hashtable<String, EmployeeCache.EmployeeRef>();
		queue = new ReferenceQueue<Employee>();
	}
	
	public synchronized static EmployeeCache getInstance(){
		if(null == employeeCache){
			employeeCache = new EmployeeCache();
		}
		return employeeCache;
	}
	
	// cache container
	private static Hashtable<String,EmployeeRef> cache = null;
	// soft index queue
	private static ReferenceQueue<Employee> queue = null ;
	
	/**
	 * Private inner class: soft index object of Employee
	 */
	private class EmployeeRef extends SoftReference<Employee>{
		private String uniqueKey = "";
		public EmployeeRef(Employee referent, ReferenceQueue<? super Employee> q) {
			super(referent, q);
			this.setUniqueKey(referent.getId());
		}
		public void setUniqueKey(String uniqueKey) {
			this.uniqueKey = uniqueKey;
		}
	}
	
	/**
	 * add element to cache
	 */
	public void put(Employee employee){
		// Clear the soft index object already in the reference queue to free up space
		clearReferenceQueue();
		EmployeeRef ref = new EmployeeRef(employee, queue);
		cache.put(ref.uniqueKey, ref);
	}
	
	private void clearReferenceQueue(){
		EmployeeRef ref = null ;
		// dequeue the data in the reference queue
		while((ref = (EmployeeRef)queue.poll()) != null){
			// Also clear the object content of the soft reference as KEY
			cache.remove(ref.uniqueKey);
		}
	}
	
	/**
	 * Get the element from the cache
	 * @param key
	 * @return
	 */
	public Employee get(String key){
		
		Employee employee = null ;
		if(cache.containsKey(key)){
			EmployeeRef employeeRef = cache.get(key);
			employee = employeeRef.get();
		}
		if(null == employee){
			employee = new Employee(key);
			EmployeeRef ref = new EmployeeRef(employee, queue);
			cache.put(key, ref);
		}
		return employee ;
	}
}




public class EmployeeCacheMain {

	private static EmployeeCache cache = EmployeeCache.getInstance();
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Employee e1 = new Employee("1", "Zhang San", "Test Department", 10000.0);
		Employee e2 = new Employee("2", "Li Si", "Development Department", 15000.0);
		cache.put(e1);
		cache.put(e2);
		
		Employee employee = cache.get("1");
		System.out.println(employee.toString());
		e2.setDepartment("Test Department");
		cache.put(e2);
		System.out.println(cache.get("2").getDepartment());
	}

}



Blog reference:
java reference type
on java object reference and object assignment

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326534980&siteId=291194637