java 强引用、软引用、弱引用、虚引用

java 强引用、软引用、弱引用、虚引用_第1张图片

 

参考:https://blog.csdn.net/junjunba2689/article/details/80601729

       这篇文章的一个评论很有特点:

强引用:

(一)强引用就是在程序代码之中普遍存在的,类似Object obj = new Object()这类的引用,
		只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象。只有当这个内存空间不被任何对象引用的时候,垃圾回收器才会去回收。

		Object obj = new Object();// 强引用
		
		String name = "漠天";     // 强引用
		
		List list = new ArrayList();
		list.add(name);			  // 强引用

		obj、name、在list集合里的数据不会释放,即使内存不足也不会

(二)所以我们在使用完对象后,可以把对象置为空,这样我的垃圾回收器gc就会在合适的时候释放掉为该对象分配的内存空间

		obj = null;  
		name = null; 
		
		list.clear();(ArrayList的clear方法是把list对象集合里的数据对象挨个置空 = null;但是list对象还在持有强引用,便于add新的数据)
		list = null; // 再次把对象置空 彻底释放强引用

		当然,在置为空前要确认是否不再需要使用该对象了,如果需要随时使用这个对象,则不能这么做,否则会出现空指针

(三)eg:

		在android的生命周期使用完强引用后,在OnDestroy()里给判断并置空

软引用:

(一)在jvm报告内存不足之前会清除所有的软引用,这样的话gc就可以收集到很多软引用释放出来的内存空间,
		从而解决内存吃紧的问题,避免内存溢出,什么时候被回收取决于gc的算法和gc运行时可用的内存大小。

		软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,
		JAVA虚拟机就会把这个软引用加入到与之关联的引用队列中

		String str = "zhuwentao";     // 强引用  

		SoftReference strSoft = new SoftReference(str);     // 使用软引用封装强引用  
		

(二) 弱引用是用来描述非必需对象的,可用来实现内存敏感的高速缓存

(三) 当内存足够大时可以把数组存入软引用,取数据时就可从内存里取数据,提高运行效率

		软引用在实际中有重要的应用,例如浏览器的后退按钮。

		按后退时,这个后退时显示的网页内容是重新进行请求还是从缓存中取出呢?这就要看具体的实现策略了。

		(1)如果一个网页在浏览结束时就进行内容的回收,则按后退查看前面浏览过的页面时,需要重新构建

		(2)如果将浏览过的网页存储到内存中会造成内存的大量浪费,甚至会造成内存溢出,这时候就可以使用软引用

弱引用:

(一)弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。
		在垃圾回收器线程扫描它 所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。
		不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。
		
		String str = "漠天";     // 强引用  

		WeakReference strWeak = new WeakReference(str);     // 使用弱引用封装强强引用  

(二)弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

		Object c = new Car(); //只要c还指向car object, car object就不会被回收
		WeakReference weakCar = new WeakReference(Car)(car);

		当要获得weak reference引用的object时, 首先需要判断它是否已经被回收:

			weakCar.get();//如果此方法为空, 那么说明weakCar指向的对象已经被回收了.

			eg:if(weakCar.get()!=null){} 

		如果这个对象是偶尔的使用,并且希望在使用时随时就能获取到,但又不想影响此对象的垃圾收集,那么你应该用 Weak Reference 来记住此对象,而不是使用一般的Reference。
(三)例如 Handler 的弱引用,防止内存泄漏:

	public class MainActivity extends AppCompatActivity {

		private Handler handler  ;
	 
		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_main);
	 
			handler = new MyHandler( this ) ;
	 
			new Thread(new Runnable() {
				@Override
				public void run() {
				   handler.sendEmptyMessage( 0 ) ;
				}
			}).start() ;
	 
		}
	 
		private static class MyHandler extends Handler {
			WeakReference weakReference ;
	 
			public MyHandler(MainActivity activity ){
				weakReference  = new WeakReference( activity) ;
			}
	 
			@Override
			public void handleMessage(Message msg) {
				super.handleMessage(msg);
				if ( weakReference.get() != null ){
					// update android ui
				}
			}
		}
	 
	}

虚引用:

(一)“虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。
		如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。
		虚引用主要用来跟踪对象被垃圾回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。
		
		要注意的是,虚引用必须和引用队列关联使用,当垃圾回收器准备回收一个对象时,
		如果发现它还有虚引用,就会把这个虚引用加入到与之 关联的引用队列中。
		程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。
		如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

(二)使用:

		ReferenceQueue queue = new ReferenceQueue();
		PhantomReference pr = new PhantomReference(new User(), queue);
		System.out.println(pr.get());

注意:

	特别注意,在实际程序设计中一般很少使用弱引用与虚引用,使用软用的情况较多,
	这是因为软引用可以加速JVM对垃圾内存的回收速度,可以维护系统的运行安全,防止内存溢出(OutOfMemory)等问题的产生。

转载文章总结:

	强引用:
		String str = “abc”;
		list.add(str);
		
	软引用:
		如果弱引用对象回收完之后,内存还是报警,继续回收软引用对象
		
	弱引用:
		如果虚引用对象回收完之后,内存还是报警,继续回收弱引用对象
		
	虚引用:
		虚拟机的内存不够使用,开始报警,这时候垃圾回收机制开始执行System.gc(); String s = “abc”;如果没有对象回收了, 就回收没虚引用的对象

个人感觉:

	强引用:
		
		平常使用的对象,使用注意及时置空释放即可
		
	软引用:
		
		使用软引用队列处理比较吃内存的对象,比如:处理图片加载、文件下载、缓存大量数据到内存等
		
	弱引用和虚引用:自己用作练习和测试即可

 

你可能感兴趣的:(Java)