个人小笔记之-java Semaphore

来源:互联网 发布:知乎离职员工 编辑:程序博客网 时间:2024/06/07 05:44

今天在仿照慕课网上自己写一个Android的imgeLoader的时候用到了信号量Semaphore,其实这也是线程安全的一种实现方式,以前在学校操作系统的时候,关于读写操作这一块也是用到了信号量,今天在这里也将这个信号量给总结一下,首先先贴一下今天大致写的代码 。其中有信号量的使用

package FileUtils;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.util.DisplayMetrics;import android.util.Log;import android.view.ViewGroup;import android.widget.ImageView;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.lang.reflect.Field;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.util.LinkedList;import java.util.concurrent.Executor;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;/** * Created by Administrator on 2017/4/10. */public class ImageLoader implements FileLoader<Bitmap>  {    /**     * 队列的调度方式     *     * @author zhy     *     */    public enum Type    {        FIFO, LIFO    }    //图片的缓存机制    ImageCache localImageCache = new ImageMemoryCache();    ImageCache URLImageCache = new ImageDoubleCache();    /**     * 队列的调度方式     */    private Type mType = Type.LIFO;    /**     * 任务队列     */    private LinkedList<Runnable> mTasks;    /**     * 轮询的线程     */    private Thread mPoolThread;    private Handler mPoolThreadHander;    //下载线程池线程池,线程池数量为cpu数量    //加载线程池,默认大小为1    ExecutorService mThreadPool;    private int ThreadCount = 1;    //运行在UI线程的Handler用于给ImgeView设置图片    Handler mHandler;    //引入一个1的信号量,确保mPoolThreadHander不为空    private volatile Semaphore mSemaphore = new Semaphore(0);    //引入一个信号量,防止加入任务速度过快    private volatile Semaphore mPoolSemaphore;    private static ImageLoader instance;    public  static  ImageLoader getInstance(){        if(instance==null){            synchronized (ImageLoader.class){                if(instance==null){                    instance = new ImageLoader(1, Type.LIFO);                }            }        }        return instance;    }    @Override    public Bitmap getFile(String url) {        return null;    }    private ImageLoader(int threadCount,Type type){        init(threadCount,type);    }    private void init(int threadCount, Type type) {        //初始化变量        mThreadPool = Executors.newFixedThreadPool(threadCount);        mPoolSemaphore = new Semaphore(threadCount);        mTasks = new LinkedList<Runnable>();        mType = type == null ? Type.LIFO : type;        //开启轮训线程        mPoolThread = new Thread(new Runnable() {            @Override            public void run() {                //  初始化轮询消息队列                Looper.prepare();                mPoolThreadHander = new Handler(){                    @Override                    public void handleMessage(Message msg) {                        //取出任务,并且进行执行                        mThreadPool.execute(getTask());                        //信号量阻塞                        try {                            mPoolSemaphore.acquire();                        } catch (InterruptedException e) {                            e.printStackTrace();                        }                    }                };                //handler初始化完成后,释放信号量,这时候才能添加任务                mSemaphore.release();                //开始消息队列循环                Looper.loop();            }        });        //开启轮询线程        mPoolThread.start();    }    //取出轮序线程中的任务    private synchronized  Runnable getTask(){        //判断轮序的顺序        if(mType==Type.FIFO){            return  mTasks.removeFirst();        }        if(mType==Type.LIFO){            return mTasks.removeLast();        }        return null;    }    //添加任务到轮询线程    private synchronized void addTask(Runnable task){        if( mPoolThreadHander==null) {            try {                mSemaphore.acquire();            } catch (InterruptedException e) {                e.printStackTrace();            }        }        mTasks.add(task);        mPoolThreadHander.sendEmptyMessage(0x110);    }    public void loadImage(final String path, final ImageView imgeView, boolean  isFromLocal){        imgeView.setTag(path);        mHandler =new Handler(){            @Override            public void handleMessage(Message msg) {                ImageHolder holder = (ImageHolder) msg.obj;                String path = holder.key;                Bitmap bitmap =holder.bitmap;                if(path.equals(imgeView.getTag().toString())){                    imgeView.setImageBitmap(bitmap);                }            }        };        //判断图片加载方式        if(isFromLocal){            Bitmap bitmap= localImageCache.get(path);            if(bitmap!=null){                ImageHolder holder = new ImageHolder();                holder.key=path;                holder.bitmap =bitmap;                Message message = new Message();                message.obj =holder;                mHandler.sendMessage(message);            }else{                addTask(new Runnable() {                    @Override                    public void run() {                        //根据path从内存中获取,并且进行压缩发,handler发送                       Bitmap bitmap = BitmapFactory.decodeFile(path);                        //进行压缩                        ImageSize imageSize = getImageViewSize(imgeView);                        bitmap = decodeSampledBitmapFromResource(bitmap,imageSize.width,imageSize.height);                        ImageHolder holder = new ImageHolder();                        holder.key=path;                        holder.bitmap =bitmap;                        Message message = new Message();                        message.obj =holder;                        mHandler.sendMessage(message);                        mPoolSemaphore.release();                    }                });            }        }else {            //从网络的加载方式            Bitmap bitmap = URLImageCache.get(path);            if (bitmap != null) {                ImageHolder holder = new ImageHolder();                holder.key = path;                holder.bitmap = bitmap;                Message message = new Message();                message.obj = holder;                mHandler.sendMessage(message);            } else {                addTask(new Runnable() {                    @Override                    public void run() {                        //根据path从网络中获取中获取,并且进行压缩发,handler发送                        Bitmap bitmap = BitmapFactory.decodeFile(path);                        //进行压缩                        ImageSize imageSize = getImageViewSize(imgeView);                        bitmap = decodeSampledBitmapFromResource(bitmap, imageSize.width, imageSize.height);                        ImageHolder holder = new ImageHolder();                        holder.key = path;                        holder.bitmap = bitmap;                        Message message = new Message();                        message.obj = holder;                        mHandler.sendMessage(message);                        mPoolSemaphore.release();                    }                });            }        }    }    //图片显示    public void loadLocalImage(String path,ImageView imgeView){        loadImage(path,imgeView,true);    }    public void LoadURLImage(String path,ImageView imgeView){        loadImage(path,imgeView,false);    }    //图片的压缩处理    //根据imageView获取相应的宽高    private ImageSize getImageViewSize(ImageView imgeView){        ImageSize imageSize = new ImageSize();        //获取屏幕的宽和高        DisplayMetrics displayMetrics = imgeView.getResources().getDisplayMetrics();        ViewGroup.LayoutParams params = imgeView.getLayoutParams();        int width = params.width== ViewGroup.LayoutParams.WRAP_CONTENT?0:imgeView.getWidth();        int height = params.height== ViewGroup.LayoutParams.WRAP_CONTENT?0:imgeView.getHeight();        if(width<=0){            width =params.width;        }        if(width<=0){            width = getImageViewFieldValue(imgeView,"mMaxWidth");        }if(width<=0){            width = displayMetrics.widthPixels;        }        //高度        if( height<=0){            height =params. height;        }        if( height<=0){            height = getImageViewFieldValue(imgeView,"mMaxHeight");        }if(width<=0){            height = displayMetrics.heightPixels;        }        imageSize.height=height;        imageSize.width = width;        return  imageSize;    }    /**     * 反射获得ImageView设置的最大宽度和高度     *     * @param object     * @param fieldName     * @return     */    private static int getImageViewFieldValue(Object object, String fieldName)    {        int value = 0;        try        {            Field field = ImageView.class.getDeclaredField(fieldName);            field.setAccessible(true);            int fieldValue = (Integer) field.get(object);            if (fieldValue > 0 && fieldValue < Integer.MAX_VALUE)            {                value = fieldValue;                Log.e("TAG", value + "");            }        } catch (Exception e)        {        }        return value;    }    // 计算insamplesize用于压缩图片    private int caculateInsampleSize(BitmapFactory.Options option,int reqWidth,int reqHeight){        int inSampleSize = 1;        int width =option.outWidth;        int height = option.outHeight;        if(width>reqWidth&&height>reqHeight){            int widthRadius = Math.round((float) width / (float) reqWidth);            int heightRadius =  Math.round((float) height / (float) reqHeight);            inSampleSize = Math.max(widthRadius,heightRadius);        }        return inSampleSize;    }    //根据计算的出的压缩比例    private Bitmap decodeSampledBitmapFromResource( Bitmap image, int reqWidth, int reqHeight)    {        ByteArrayOutputStream out = new ByteArrayOutputStream();        image.compress(Bitmap.CompressFormat.JPEG,100,out);        // 第一次解析将inJustDecodeBounds设置为true,来获取图片大小        final BitmapFactory.Options options = new BitmapFactory.Options();        options.inJustDecodeBounds = true;        // 调用上面定义的方法计算inSampleSize值        options.inSampleSize = caculateInsampleSize(options, reqWidth,                reqHeight);        // 使用获取到的inSampleSize值再次解析图片        options.inJustDecodeBounds = false;        ByteArrayInputStream isBm =  new  ByteArrayInputStream(out.toByteArray());        Bitmap bitmap = BitmapFactory.decodeStream(isBm,null,options);        return bitmap;    }    public void  setURLImageCache(ImageCache imageCache){        this.URLImageCache = imageCache;    }    //UI线程的handler图片加载    //图片宽高    class ImageSize{        int width;        int height;    }    //imageholder    class ImageHolder{        String key;        Bitmap bitmap;    }}

  Semaphore是一种基于计数的信号量。它可以设定一个阈值,基于此,多个线程竞争获取许可信号,做完自己的申请后归还,超过阈值后,线程申请许可信号将会被阻塞

acquire方法会申请信号量,但是当信号量已经达到阈值的时候,这时候线程就会再次堵塞,知道其他线程release后,自己抢占的信号量才会继续往下走,所以对于java多线程,信号量也是加锁的一种办法

0 0
原创粉丝点击