您的位置:首页 > 编程语言 > Java开发

java中的引用和GC

2016-01-25 11:40 453 查看

java中的引用和GC

简介:java中有四种引用:强软弱虚

强引用: strong Reference,=就是强引用方式,即时出现OOM,GC都不会销毁强引用

软引用: soft Reference,当Java所管理的内存趋于阈值时,GC将会销毁一部分软引用,释放内存。

弱引用: weak Reference,就算Java所管理的内存没有趋于阈值,GC都有可能销毁部分弱引用。

虚引用: 按照GC回收优先度,虚引用肯定是最早被回收的,这个基本开发的时候不会用到

GC:Garbage Collection,是java和C++的主要区别之一,这里简单介绍一下,如果有时间再去写详细介绍,

垃圾回收机制,java程序员不需要去自己回收内存,不想C和C++的程序员,但是电脑去执行回收机制肯定做不到人那样根据需要去回收,所以会造成一定程序的内存浪费,这就是为什么对安卓里面的OOM很重视。

GC在执行的时候模,所有的线程都会被暂停。当Java所管理内存趋于阈值时,GC的执行频率将会加快,这时候就会出现卡顿的感觉,用户体验杀手。

下面结合一些代码讲一下这个问题

早期的时候,图片显示是手机的一个大问题,因为早期手机内存过小,后来出现了高压缩率的图片jpg之类的图片问题得到部分改善,后来内存又扩大,这个问题基本得到了解决,但是随着时间,图片的数量越来越多,再结合服务器,考虑到流量问题。下面具体分析listview结合服务器的图片下载问题

首先,listview采用了viewholder和adapter进行了优化,但是如果涉及到图片,如果单纯的把图片存在RAM部分,那么加载速度会非常慢,而listview的滑动操作是很快的,这时候就会出现图片没有加载完成所显示的view就不需要了,影响用户体验,之前有写过解决这个问题的方法,是采用了异步任务加中断的方式,但是这种情况适用性有限,而且不好用,性能提升不明显

3. 速度慢的原因是需要去ram中读取的图片的速度过慢导致,所以想到一个办法,将图片存入内存,但当图片过多的时候会出现OOM问题,java程序员是没有办法回收不用的图片内存的,GC这个时候也不会去回收强引用,所以要使用软应用甚至弱引用来解决,这其实是一个二级缓存机制,具体请看下面的代码

package cn.myapp.musicclient.util;

import java.io.File;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.util.EntityUtils;

import com.tarena.musicclient.R;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.ListView;

/**
* 图片异步批量加载的工具类
* 提供图片的内存缓存与文件缓存
*/
public class ImageLoader {
//声明工作线程
private Thread workThread;
private boolean isLoop=true;
//存储缓存图片
private HashMap<String, SoftReference<Bitmap>> cache=new HashMap<String, SoftReference<Bitmap>>();
private Context context;
//生成任务集合
private List<ImageLoadTask> tasks=new ArrayList<ImageLoadTask>();
private AbsListView listView;
//声明handler
private Handler handler=new  Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case HANDLER_IMAGE_LOAD_SUCCESS:
//更新ImageView
ImageLoadTask task=(ImageLoadTask)msg.obj;
//通过position做的tag 找到相应的ImageView
ImageView ivAlbum=(ImageView)listView.findViewWithTag(task.position);
if(ivAlbum!=null){
Bitmap bitmap=task.bitmap;
if(bitmap!=null){
ivAlbum.setImageBitmap(bitmap);
}else{
ivAlbum.setImageResource(R.drawable.ic_launcher);
}
}
break;
}
}
};
public static final int HANDLER_IMAGE_LOAD_SUCCESS=0;

public ImageLoader(Context context, AbsListView listView) {
this.listView=listView;
this.context=context;
//初始化workThread
workThread=new Thread(){
public void run() {
//不断的查看集合中是否有数据
while(isLoop){
//如果集合中有图片下载任务
if(!tasks.isEmpty()){
//把第一个图片下载任务获取并执行
ImageLoadTask task=tasks.remove(0);
//直接下载图片
Bitmap bitmap=loadBitmap(task.path);
//把bitmap设置到相应的ImageView中
//需要在主线程中  (发消息给handler)
task.bitmap=bitmap;
Message msg=new Message();
msg.what=HANDLER_IMAGE_LOAD_SUCCESS;
msg.obj=task;
handler.sendMessage(msg);
}else{
//如果任务集合中已经没有任务了
//那么线程等待
synchronized (workThread) {
try {
workThread.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
};
workThread.start();
}

/**
* 通过path 发送http请求 下载图片
* @param path
* images/junshengjinshi.jpg
* @return
* @throws IOException
* @throws ClientProtocolException
*/
public Bitmap loadBitmap(String path) {
try {
String url=GlobalConsts.BASEURL+path;
HttpEntity entity=HttpUtils.send(HttpUtils.METHOD_GET, url, null);
//把entity转成Bitmap
byte[] bytes=EntityUtils.toByteArray(entity);
Bitmap bitmap=BitmapUtils.loadBitmap(bytes, 50, 50);
//向内存缓存中 缓存图片
cache.put(path, new SoftReference<Bitmap>(bitmap));
//向缓存目录中 保存图片
File targetFile=new File(context.getCacheDir(), path);
//targetFile:   /data/data/com.xx.xx/cache/images/jsjs.jpg
BitmapUtils.save(bitmap, targetFile);

return bitmap;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

/**
* 显示图片
* @param imageView  控件
* @param path 图片路径
* @param position 图片的位置
*/
public void displayImage(ImageView imageView, String path, int position){
imageView.setTag(position);

4000
//从缓存中获取  如果有 则直接显示
//不在向任务集合中添加任务了。
SoftReference<Bitmap> ref=cache.get(path);
if(ref!=null){
Bitmap bitmap=ref.get();
if(bitmap!=null){
Log.i("info", "这是从内存缓存中读取的图片..");
imageView.setImageBitmap(bitmap);
return;
}
}
//内存缓存中没有图片 则去文件缓存中读取
String filepath=new File(context.getCacheDir(),path).getAbsolutePath();
Bitmap bitmap=BitmapUtils.loadBitmap(filepath);
if(bitmap!=null){
Log.i("info", "从文件缓存中读取的图片..");
imageView.setImageBitmap(bitmap);
//存入内存缓存
cache.put(path, new SoftReference<Bitmap>(bitmap));
return;
}

//向任务集合中添加任务
ImageLoadTask task=new ImageLoadTask();
task.path=path;//保存图片路径
task.position=position;
tasks.add(task);
//唤醒工作线程workThread  起来干活
synchronized (workThread) {
workThread.notify();
}
}

class ImageLoadTask{
String path;
Bitmap bitmap;
int position;
}

public void stopThread() {
isLoop=false;
synchronized (workThread) {
workThread.notify();
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  内存 管理 oom java