信号量,了解过操作系统的人都知道,信号量是用来做什么的···

在Android中,已经提供了Semaphore来帮助我们使用~

那么,在开发中这家伙有什么用呢?

用的地方不多,但是却真的是好用至极!

#0 举个栗子

我相信很多人在开发中都会遇到这样的事情:当要对一个资源进行多次数据读取并且修改操作时,会遇到执行的速度快慢不一致导致修改值发生改变的情况。

比如如下代码:

    private void Start() {
for (int i = 10; i >= 0; i--) {
LogString = "num:" + i;
printLogString(i);
}
} private void printLogString(final int delayTime) {
Log.e("TAG", "Runnable" + delayTime);
new Thread(new Runnable() {
@Override
public void run() {
Log.e("TAG", LogString);
}
}).start();
}

打印出的日志会不一致,如:

04-03 15:33:07.294 17078-17078/com.gao.luna.semaphoretest E/TAG: Runnable10
04-03 15:33:07.296 17078-17078/com.gao.luna.semaphoretest E/TAG: Runnable9
04-03 15:33:07.296 17078-17777/com.gao.luna.semaphoretest E/TAG: num:9
04-03 15:33:07.297 17078-17078/com.gao.luna.semaphoretest E/TAG: Runnable8
04-03 15:33:07.297 17078-17078/com.gao.luna.semaphoretest E/TAG: Runnable7
04-03 15:33:07.298 17078-17778/com.gao.luna.semaphoretest E/TAG: num:7
04-03 15:33:07.299 17078-17078/com.gao.luna.semaphoretest E/TAG: Runnable6
04-03 15:33:07.299 17078-17779/com.gao.luna.semaphoretest E/TAG: num:6
04-03 15:33:07.300 17078-17078/com.gao.luna.semaphoretest E/TAG: Runnable5
04-03 15:33:07.301 17078-17780/com.gao.luna.semaphoretest E/TAG: num:5
04-03 15:33:07.301 17078-17078/com.gao.luna.semaphoretest E/TAG: Runnable4
04-03 15:33:07.302 17078-17781/com.gao.luna.semaphoretest E/TAG: num:4
04-03 15:33:07.303 17078-17078/com.gao.luna.semaphoretest E/TAG: Runnable3
04-03 15:33:07.303 17078-17782/com.gao.luna.semaphoretest E/TAG: num:3
04-03 15:33:07.304 17078-17783/com.gao.luna.semaphoretest E/TAG: num:3
04-03 15:33:07.305 17078-17078/com.gao.luna.semaphoretest E/TAG: Runnable2
04-03 15:33:07.305 17078-17784/com.gao.luna.semaphoretest E/TAG: num:2
04-03 15:33:07.305 17078-17078/com.gao.luna.semaphoretest E/TAG: Runnable1
04-03 15:33:07.306 17078-17078/com.gao.luna.semaphoretest E/TAG: Runnable0
04-03 15:33:07.306 17078-17785/com.gao.luna.semaphoretest E/TAG: num:0
04-03 15:33:07.308 17078-17786/com.gao.luna.semaphoretest E/TAG: num:0
04-03 15:33:07.308 17078-17787/com.gao.luna.semaphoretest E/TAG: num:0

这和我们希望见到的num从10打印到0时不相符的。

#1 Semaphore的使用

接着上面的代码,我们加入Semaphore来解决这个问题:

 private final Semaphore semaphore = new Semaphore(0, true);

这里有个坑需要注意一下,比如说这个队列限制只有1个存在,那么在创建时要写0,写1的话,就会变成2个了···以此类推,要队列中有10个对象,需要写9···

在每次acquire后,semaphone将加入一个对象,在不release的情况下,这个对象是会一直存在的。

下面上代码:

     private final Semaphore semaphore = new Semaphore(0, true);

     private void Start() {
for (int i = 10; i >= 0; i--) {
try {
Log.e("Semaphore", "semaphore.acquire();" + i);
semaphore.acquire();
} catch (Exception ex) {
Log.e("Semaphore", ex.getMessage());
}
LogString = "num:" + i;
printLogString(i);
}
} private void printLogString(final int delayTime) {
new Thread(new Runnable() {
@Override
public void run() {
Log.e("Semaphore", "semaphore.release();");
Log.e("TAG", LogString);
semaphore.release();
}
}).start();
}

日志如下:

04-03 15:40:41.060 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 15:40:41.065 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();10
04-03 15:40:41.078 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();9
04-03 15:40:41.078 26200-26513/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 15:40:41.084 26200-26513/com.gao.luna.semaphoretest E/TAG: num:10
04-03 15:40:41.086 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();8
04-03 15:40:41.086 26200-26514/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 15:40:41.086 26200-26514/com.gao.luna.semaphoretest E/TAG: num:9
04-03 15:40:41.086 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();7
04-03 15:40:41.087 26200-26515/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 15:40:41.087 26200-26515/com.gao.luna.semaphoretest E/TAG: num:8
04-03 15:40:41.087 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();6
04-03 15:40:41.088 26200-26516/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 15:40:41.088 26200-26516/com.gao.luna.semaphoretest E/TAG: num:7
04-03 15:40:41.088 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();5
04-03 15:40:41.088 26200-26517/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 15:40:41.088 26200-26517/com.gao.luna.semaphoretest E/TAG: num:6
04-03 15:40:41.089 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();4
04-03 15:40:41.089 26200-26518/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 15:40:41.089 26200-26518/com.gao.luna.semaphoretest E/TAG: num:5
04-03 15:40:41.090 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();3
04-03 15:40:41.090 26200-26519/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 15:40:41.091 26200-26519/com.gao.luna.semaphoretest E/TAG: num:4
04-03 15:40:41.091 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();2
04-03 15:40:41.092 26200-26520/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 15:40:41.092 26200-26520/com.gao.luna.semaphoretest E/TAG: num:3
04-03 15:40:41.092 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();1
04-03 15:40:41.093 26200-26521/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 15:40:41.093 26200-26521/com.gao.luna.semaphoretest E/TAG: num:2
04-03 15:40:41.094 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();0
04-03 15:40:41.094 26200-26522/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 15:40:41.094 26200-26522/com.gao.luna.semaphoretest E/TAG: num:1
04-03 15:40:41.095 26200-26523/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 15:40:41.095 26200-26523/com.gao.luna.semaphoretest E/TAG: num:0

这里我们可以很清晰的看到,num从10顺序变为了0。

#2 再加点延迟试试

现在,我们再在其中增加一些sleep代码,再来测试看看。

     private final Semaphore semaphore = new Semaphore(0, true);

     private void Start() {
for (int i = 10; i >= 0; i--) {
try {
Log.e("Semaphore", "semaphore.acquire();" + i);
semaphore.acquire();
} catch (Exception ex) {
Log.e("Semaphore", ex.getMessage());
}
LogString = "num:" + i;
printLogString(i);
}
} private void printLogString(final int delayTime) {
Log.e("TAG", "Runnable" + delayTime);
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(delayTime * 10);
} catch (Exception ex) {
Log.e("delayTime", ex.getMessage());
}
Log.e("Semaphore", "semaphore.release();");
Log.e("TAG", LogString);
semaphore.release();
}
}).start();
}

然后看看日志:

04-03 16:15:34.028 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 16:15:34.028 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();10
04-03 16:15:34.028 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable10
04-03 16:15:34.029 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();9
04-03 16:15:34.129 18148-18230/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 16:15:34.129 18148-18230/com.gao.luna.semaphoretest E/TAG: num:10
04-03 16:15:34.130 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable9
04-03 16:15:34.130 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();8
04-03 16:15:34.221 18148-18232/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 16:15:34.221 18148-18232/com.gao.luna.semaphoretest E/TAG: num:9
04-03 16:15:34.221 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable8
04-03 16:15:34.222 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();7
04-03 16:15:34.302 18148-18245/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 16:15:34.302 18148-18245/com.gao.luna.semaphoretest E/TAG: num:8
04-03 16:15:34.303 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable7
04-03 16:15:34.382 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();6
04-03 16:15:34.453 18148-18251/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 16:15:34.453 18148-18251/com.gao.luna.semaphoretest E/TAG: num:7
04-03 16:15:34.453 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable6
04-03 16:15:34.462 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();5
04-03 16:15:34.523 18148-18266/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 16:15:34.523 18148-18266/com.gao.luna.semaphoretest E/TAG: num:6
04-03 16:15:34.523 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable5
04-03 16:15:34.529 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();4
04-03 16:15:34.579 18148-18267/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 16:15:34.579 18148-18267/com.gao.luna.semaphoretest E/TAG: num:5
04-03 16:15:34.579 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable4
04-03 16:15:34.635 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();3
04-03 16:15:34.675 18148-18268/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 16:15:34.675 18148-18268/com.gao.luna.semaphoretest E/TAG: num:4
04-03 16:15:34.675 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable3
04-03 16:15:34.676 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();2
04-03 16:15:34.706 18148-18272/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 16:15:34.706 18148-18272/com.gao.luna.semaphoretest E/TAG: num:3
04-03 16:15:34.706 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable2
04-03 16:15:34.733 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();1
04-03 16:15:34.753 18148-18275/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 16:15:34.753 18148-18275/com.gao.luna.semaphoretest E/TAG: num:2
04-03 16:15:34.753 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable1
04-03 16:15:34.754 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();0
04-03 16:15:34.764 18148-18280/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 16:15:34.764 18148-18280/com.gao.luna.semaphoretest E/TAG: num:1
04-03 16:15:34.764 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable0
04-03 16:15:34.765 18148-18281/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
04-03 16:15:34.765 18148-18281/com.gao.luna.semaphoretest E/TAG: num:0

仍然没有问题~~~

#3 需要注意的地方

如果使用了Handler,需要注意的是,Handler会返回主线程来进行调用,如果在Handler未执行时在acquire地方暂停了,那么Handler是不会执行的。需要特别留意。

下面是全部的代码:

 package com.gao.luna.semaphoretest;

 import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View; import java.util.concurrent.Semaphore; public class MainActivity extends AppCompatActivity { private String LogString; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(onClickListener);
} View.OnClickListener onClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e("Semaphore", "semaphore.release();");
semaphore.release();
Start();
}
}; private final Semaphore semaphore = new Semaphore(0, true); private void Start() {
for (int i = 10; i >= 0; i--) {
try {
Log.e("Semaphore", "semaphore.acquire();" + i);
semaphore.acquire();
} catch (Exception ex) {
Log.e("Semaphore", ex.getMessage());
}
LogString = "num:" + i;
printLogString(i);
}
} private void printLogString(final int delayTime) {
Log.e("TAG", "Runnable" + delayTime);
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(delayTime * 10);
} catch (Exception ex) {
Log.e("delayTime", ex.getMessage());
}
Log.e("Semaphore", "semaphore.release();");
Log.e("TAG", LogString);
semaphore.release();
}
}).start();
}
}

全部代码

Android中的Semaphore的更多相关文章

  1. 阿里面试官:Android中binder机制的实现原理及过程?

    Binder 是 Android 系统中非常重要的组成部分.Android 系统中的许多功能建立在 Binder 机制之上.在这篇文章中,我们会对 Android 中的 Binder 在系统架构中的作 ...

  2. Android中的LinearLayout布局

    LinearLayout : 线性布局 在一般情况下,当有很多控件需要在一个界面列出来时,我们就可以使用线性布局(LinearLayout)了,  线性布局是按照垂直方向(vertical)或水平方向 ...

  3. Android中BroadcastReceiver的两种注册方式(静态和动态)详解

    今天我们一起来探讨下安卓中BroadcastReceiver组件以及详细分析下它的两种注册方式. BroadcastReceiver也就是"广播接收者"的意思,顾名思义,它就是用来 ...

  4. Android中使用ExpandableListView实现微信通讯录界面(完善仿微信APP)

    之前的博文<Android中使用ExpandableListView实现好友分组>我简单介绍了使用ExpandableListView实现简单的好友分组功能,今天我们针对之前的所做的仿微信 ...

  5. Android中ListView实现图文并列并且自定义分割线(完善仿微信APP)

    昨天的(今天凌晨)的博文<Android中Fragment和ViewPager那点事儿>中,我们通过使用Fragment和ViewPager模仿实现了微信的布局框架.今天我们来通过使用Li ...

  6. Android中Fragment和ViewPager那点事儿(仿微信APP)

    在之前的博文<Android中使用ViewPager实现屏幕页面切换和引导页效果实现>和<Android中Fragment的两种创建方式>以及<Android中Fragm ...

  7. Android中Fragment与Activity之间的交互(两种实现方式)

    (未给Fragment的布局设置BackGound) 之前关于Android中Fragment的概念以及创建方式,我专门写了一篇博文<Android中Fragment的两种创建方式>,就如 ...

  8. 【月入41万】Mono For Android中使用百度地图SDK

    借助于Mono For Android技术,.Net开发者也可以使用自己熟悉的C#语言以及.Net来开发Android应用.由于Mono For Android把Android SDK中绝大部分类库都 ...

  9. mono for android中使用dapper或petapoco对sqlite进行数据操作

    在mono for android中使用dapper或petapoco,很简单,新建android 类库项目,直接把原来的文件复制过来,对Connection连接报错部分进行注释和修改就可以运行了.( ...

随机推荐

  1. jquery checkbox操作

    一.通过选择器选取CheckBox: 1.给CheckBox设置一个id属性,通过id选择器选取: <input type="checkbox" name="myB ...

  2. Spring 整体架构

    1. Core Container:核心容器(core.Beans.Context.Expression Language   Core.Beans框架基础构成,提供IOC.依赖注入特性.BeanFa ...

  3. 【转】虚拟机VMware3种网络模式(桥接、nat、Host-only)的工作原理

     VMware网络配置详解一:三种网络模式简介 安装好虚拟机以后,在网络连接里面可以看到多了两块网卡: 其 中VMnet1是虚拟机Host-only模式的网络接口,VMnet8是NAT模式的网络接口, ...

  4. SQL Server锁定【2015.12.17】

    锁定的体系分类   1.表级锁 保证数据在逻辑上的一致性. 包含:行级锁.分页锁.表.数据分页.LOB分页以及索引叶子级锁. 2.闩 保证数据在物理上的一致性,系统采用,比锁少耗资源,对用户不可见. ...

  5. 深入理解linux系统的目录结构(总结的非常详细)

    对于每一个Linux学习者来说,了解Linux文件系统的目录结构,是学好Linux的至关重要的一步.,深入了解linux文件目录结构的标准和每个目录的详细功能,对于我们用好linux系统只管重要,下面 ...

  6. ixgbe 82599 固定源与目标, UDP, 64字节小包, 1488w pps 单核CPU软中断sirq 100%

    ixgbe 82599 固定源与目标, UDP, 64字节小包, 1488w pps 单核CPU软中断sirq 100% 注: 测试使用, 正常应用不要开启 五元组不同, 开启ntupleethtoo ...

  7. 大话设计模式C++版——表驱动法改造简单工厂

    上回<大话设计模式C++版——简单工厂模式>中指出了简单工厂模式的缺陷,即违背了开发—封闭原则,其主要原因是由于switch的判断结构的使用,使修改或添加新的对象时需要改动简单工厂类的代码 ...

  8. 《硝烟中的Scrum和XP》:作者主导Scrum过程的实战经验,四星推荐

    本书作者是开发团队Leader,本书记录了他带领团队实施Scurm过程中的经验教训.全书短小精悍,言简意赅. 以下是书中一些观点信息的摘抄: 1:Nokia总结出的迭代开发的基本要求:1.1:迭代要有 ...

  9. C#笔记---动态类(Dynamic)应用

    背景: 在Coding中有时候会遇到一些需要解析的数据,可是数据的字段数量和名称未统一,我们没法定义实体类来对应.那么我们就会想到通过C#的dynamic动态类来实现,如果大家注意的话一些ORM框架里 ...

  10. 【温故而知新-Javascript】使用拖放

    HTML5 添加了对拖放(drag and drop)的支持.我们之前只能依靠jQuery 这样的JavaScript库才能处理这种操作.把拖放内置到浏览器的好处是它可以正确的集成到操作系统中,而且正 ...