信号量
来源:互联网 发布:钣金激光切割机编程 编辑:程序博客网 时间:2024/05/22 14:41
简介
信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。
一个计数信号量。从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。拿到信号量的线程可以进入代码,否则就等待。通过acquire()和release()获取和释放访问许可。
场景1:
我们在一个轮询线程中初始化一个轮询handler
private void init(int threadCount, Type type){ // loop thread mPoolThread = new Thread() { @Override public void run() { try { // 请求一个信号量 mSemaphore.acquire(); } catch (InterruptedException e) { } Looper.prepare(); mPoolThreadHander = new Handler() { @Override public void handleMessage(Message msg) { //线程池取出一个任务执行 mThreadPool.execute(getTask()); try { mPoolSemaphore.acquire(); } catch (InterruptedException e) { } } }; // 释放一个信号量 mSemaphore.release(); Looper.loop(); } }; mPoolThread.start(); // 获取应用程序最大可用内存 int maxMemory = (int) Runtime.getRuntime().maxMemory(); int cacheSize = maxMemory / 8; mLruCache = new LruCache<String, Bitmap>(cacheSize) { //测量每个Bitmap的内存大小 @Override protected int sizeOf(String key, Bitmap value) { return value.getRowBytes() * value.getHeight(); }; }; mThreadPool = Executors.newFixedThreadPool(threadCount); mPoolSemaphore = new Semaphore(threadCount); mTasks = new LinkedList<Runnable>(); mType = type == null ? Type.LIFO : type;}而外部调用的函数需要使用这个handler 我们不确定当我们使用这个handler时 他是否已经在轮询线程中初始化了
这是我们引入信号量:
/** * 引入一个值为1的信号量,防止mPoolThreadHander未初始化完成 */private volatile Semaphore mSemaphore = new Semaphore(1);
/** * 添加一个任务 * * @param runnable */private synchronized void addTask(Runnable runnable){ try { // 请求信号量,防止mPoolThreadHander为null if (mPoolThreadHander == null) mSemaphore.acquire(); } catch (InterruptedException e) { } mTasks.add(runnable); mPoolThreadHander.sendEmptyMessage(0x110);}
同时添加synchronized关键字 同时只有一个线程可以访问 若handler未能初始化则信号量为0则阻塞 等待init中的thread初始化完成后
release 信号量则为1 这时addTask则可以继续向下执行了。
场景2:
/** * 引入一个值为1的信号量,使得线程池内部也有一个阻塞线程,防止加入任务的速度过快,使LIFO效果不明显 */private volatile Semaphore mPoolSemaphore;
mPoolSemaphore = new Semaphore(threadCount);
每执行完一个任务release一个
addTask(new Runnable(){ @Override public void run() { ImageSize imageSize = getImageViewWidth(imageView); int reqWidth = imageSize.width; int reqHeight = imageSize.height; Bitmap bm = decodeSampledBitmapFromResource(path, reqWidth, reqHeight); addBitmapToLruCache(path, bm); ImgBeanHolder holder = new ImgBeanHolder(); holder.bitmap = getBitmapFromLruCache(path); holder.imageView = imageView; holder.path = path; Message message = Message.obtain(); message.obj = holder; // Log.e("TAG", "mHandler.sendMessage(message);"); mHandler.sendMessage(message); mPoolSemaphore.release(); }
若执行的时候无信号量则阻塞
mPoolThreadHander = new Handler(){ @Override public void handleMessage(Message msg) { //线程池取出一个任务执行 mThreadPool.execute(getTask()); try { mPoolSemaphore.acquire(); } catch (InterruptedException e) { } }};
0 0
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- <>信号量
- 信号量
- 信号量
- 第16周实践项目-归并排序
- 第十六周——【项目1 - 验证算法】
- TLD之L-K光流算法代码篇
- django queryset values&values_list
- 分享一个本人开发的angularjs+bootstrap+Spring+mybatis实现的java web系统项目
- 信号量
- Loadrunner 11 安装+汉化+破解
- 努力吧!
- 第十六周项目1(7)-并归排序
- 判断一个文件是一个文件夹还是一个文件
- 第十六周项目1-堆排序
- SVD分解
- android 同一个ImageView显示不同的图片--->level-list
- ofbiz框架入门例子详解-------查找篇