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

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

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

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

#0 举个栗子

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

比如如下代码:

  1.    private void Start() {
  2. for (int i = 10; i >= 0; i--) {
  3. LogString = "num:" + i;
  4. printLogString(i);
  5. }
  6. }
  7.  
  8. private void printLogString(final int delayTime) {
  9. Log.e("TAG", "Runnable" + delayTime);
  10. new Thread(new Runnable() {
  11. @Override
  12. public void run() {
  13. Log.e("TAG", LogString);
  14. }
  15. }).start();
  16. }

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

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

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

#1 Semaphore的使用

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

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

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

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

下面上代码:

  1. private final Semaphore semaphore = new Semaphore(0, true);
  2.  
  3. private void Start() {
  4. for (int i = 10; i >= 0; i--) {
  5. try {
  6. Log.e("Semaphore", "semaphore.acquire();" + i);
  7. semaphore.acquire();
  8. } catch (Exception ex) {
  9. Log.e("Semaphore", ex.getMessage());
  10. }
  11. LogString = "num:" + i;
  12. printLogString(i);
  13. }
  14. }
  15.  
  16. private void printLogString(final int delayTime) {
  17. new Thread(new Runnable() {
  18. @Override
  19. public void run() {
  20. Log.e("Semaphore", "semaphore.release();");
  21. Log.e("TAG", LogString);
  22. semaphore.release();
  23. }
  24. }).start();
  25. }

日志如下:

  1. 04-03 15:40:41.060 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  2. 04-03 15:40:41.065 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();10
  3. 04-03 15:40:41.078 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();9
  4. 04-03 15:40:41.078 26200-26513/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  5. 04-03 15:40:41.084 26200-26513/com.gao.luna.semaphoretest E/TAG: num:10
  6. 04-03 15:40:41.086 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();8
  7. 04-03 15:40:41.086 26200-26514/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  8. 04-03 15:40:41.086 26200-26514/com.gao.luna.semaphoretest E/TAG: num:9
  9. 04-03 15:40:41.086 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();7
  10. 04-03 15:40:41.087 26200-26515/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  11. 04-03 15:40:41.087 26200-26515/com.gao.luna.semaphoretest E/TAG: num:8
  12. 04-03 15:40:41.087 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();6
  13. 04-03 15:40:41.088 26200-26516/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  14. 04-03 15:40:41.088 26200-26516/com.gao.luna.semaphoretest E/TAG: num:7
  15. 04-03 15:40:41.088 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();5
  16. 04-03 15:40:41.088 26200-26517/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  17. 04-03 15:40:41.088 26200-26517/com.gao.luna.semaphoretest E/TAG: num:6
  18. 04-03 15:40:41.089 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();4
  19. 04-03 15:40:41.089 26200-26518/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  20. 04-03 15:40:41.089 26200-26518/com.gao.luna.semaphoretest E/TAG: num:5
  21. 04-03 15:40:41.090 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();3
  22. 04-03 15:40:41.090 26200-26519/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  23. 04-03 15:40:41.091 26200-26519/com.gao.luna.semaphoretest E/TAG: num:4
  24. 04-03 15:40:41.091 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();2
  25. 04-03 15:40:41.092 26200-26520/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  26. 04-03 15:40:41.092 26200-26520/com.gao.luna.semaphoretest E/TAG: num:3
  27. 04-03 15:40:41.092 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();1
  28. 04-03 15:40:41.093 26200-26521/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  29. 04-03 15:40:41.093 26200-26521/com.gao.luna.semaphoretest E/TAG: num:2
  30. 04-03 15:40:41.094 26200-26200/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();0
  31. 04-03 15:40:41.094 26200-26522/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  32. 04-03 15:40:41.094 26200-26522/com.gao.luna.semaphoretest E/TAG: num:1
  33. 04-03 15:40:41.095 26200-26523/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  34. 04-03 15:40:41.095 26200-26523/com.gao.luna.semaphoretest E/TAG: num:0

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

#2 再加点延迟试试

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

  1. private final Semaphore semaphore = new Semaphore(0, true);
  2.  
  3. private void Start() {
  4. for (int i = 10; i >= 0; i--) {
  5. try {
  6. Log.e("Semaphore", "semaphore.acquire();" + i);
  7. semaphore.acquire();
  8. } catch (Exception ex) {
  9. Log.e("Semaphore", ex.getMessage());
  10. }
  11. LogString = "num:" + i;
  12. printLogString(i);
  13. }
  14. }
  15.  
  16. private void printLogString(final int delayTime) {
  17. Log.e("TAG", "Runnable" + delayTime);
  18. new Thread(new Runnable() {
  19. @Override
  20. public void run() {
  21. try {
  22. Thread.sleep(delayTime * 10);
  23. } catch (Exception ex) {
  24. Log.e("delayTime", ex.getMessage());
  25. }
  26. Log.e("Semaphore", "semaphore.release();");
  27. Log.e("TAG", LogString);
  28. semaphore.release();
  29. }
  30. }).start();
  31. }

然后看看日志:

  1. 04-03 16:15:34.028 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  2. 04-03 16:15:34.028 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();10
  3. 04-03 16:15:34.028 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable10
  4. 04-03 16:15:34.029 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();9
  5. 04-03 16:15:34.129 18148-18230/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  6. 04-03 16:15:34.129 18148-18230/com.gao.luna.semaphoretest E/TAG: num:10
  7. 04-03 16:15:34.130 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable9
  8. 04-03 16:15:34.130 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();8
  9. 04-03 16:15:34.221 18148-18232/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  10. 04-03 16:15:34.221 18148-18232/com.gao.luna.semaphoretest E/TAG: num:9
  11. 04-03 16:15:34.221 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable8
  12. 04-03 16:15:34.222 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();7
  13. 04-03 16:15:34.302 18148-18245/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  14. 04-03 16:15:34.302 18148-18245/com.gao.luna.semaphoretest E/TAG: num:8
  15. 04-03 16:15:34.303 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable7
  16. 04-03 16:15:34.382 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();6
  17. 04-03 16:15:34.453 18148-18251/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  18. 04-03 16:15:34.453 18148-18251/com.gao.luna.semaphoretest E/TAG: num:7
  19. 04-03 16:15:34.453 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable6
  20. 04-03 16:15:34.462 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();5
  21. 04-03 16:15:34.523 18148-18266/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  22. 04-03 16:15:34.523 18148-18266/com.gao.luna.semaphoretest E/TAG: num:6
  23. 04-03 16:15:34.523 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable5
  24. 04-03 16:15:34.529 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();4
  25. 04-03 16:15:34.579 18148-18267/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  26. 04-03 16:15:34.579 18148-18267/com.gao.luna.semaphoretest E/TAG: num:5
  27. 04-03 16:15:34.579 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable4
  28. 04-03 16:15:34.635 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();3
  29. 04-03 16:15:34.675 18148-18268/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  30. 04-03 16:15:34.675 18148-18268/com.gao.luna.semaphoretest E/TAG: num:4
  31. 04-03 16:15:34.675 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable3
  32. 04-03 16:15:34.676 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();2
  33. 04-03 16:15:34.706 18148-18272/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  34. 04-03 16:15:34.706 18148-18272/com.gao.luna.semaphoretest E/TAG: num:3
  35. 04-03 16:15:34.706 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable2
  36. 04-03 16:15:34.733 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();1
  37. 04-03 16:15:34.753 18148-18275/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  38. 04-03 16:15:34.753 18148-18275/com.gao.luna.semaphoretest E/TAG: num:2
  39. 04-03 16:15:34.753 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable1
  40. 04-03 16:15:34.754 18148-18148/com.gao.luna.semaphoretest E/Semaphore: semaphore.acquire();0
  41. 04-03 16:15:34.764 18148-18280/com.gao.luna.semaphoretest E/Semaphore: semaphore.release();
  42. 04-03 16:15:34.764 18148-18280/com.gao.luna.semaphoretest E/TAG: num:1
  43. 04-03 16:15:34.764 18148-18148/com.gao.luna.semaphoretest E/TAG: Runnable0
  44. 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是不会执行的。需要特别留意。

下面是全部的代码:

  1. package com.gao.luna.semaphoretest;
  2.  
  3. import android.os.Bundle;
  4. import android.support.design.widget.FloatingActionButton;
  5. import android.support.v7.app.AppCompatActivity;
  6. import android.support.v7.widget.Toolbar;
  7. import android.util.Log;
  8. import android.view.View;
  9.  
  10. import java.util.concurrent.Semaphore;
  11.  
  12. public class MainActivity extends AppCompatActivity {
  13.  
  14. private String LogString;
  15.  
  16. @Override
  17. protected void onCreate(Bundle savedInstanceState) {
  18. super.onCreate(savedInstanceState);
  19. setContentView(R.layout.activity_main);
  20. Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
  21. setSupportActionBar(toolbar);
  22.  
  23. FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
  24. fab.setOnClickListener(onClickListener);
  25. }
  26.  
  27. View.OnClickListener onClickListener = new View.OnClickListener() {
  28. @Override
  29. public void onClick(View v) {
  30. Log.e("Semaphore", "semaphore.release();");
  31. semaphore.release();
  32. Start();
  33. }
  34. };
  35.  
  36. private final Semaphore semaphore = new Semaphore(0, true);
  37.  
  38. private void Start() {
  39. for (int i = 10; i >= 0; i--) {
  40. try {
  41. Log.e("Semaphore", "semaphore.acquire();" + i);
  42. semaphore.acquire();
  43. } catch (Exception ex) {
  44. Log.e("Semaphore", ex.getMessage());
  45. }
  46. LogString = "num:" + i;
  47. printLogString(i);
  48. }
  49. }
  50.  
  51. private void printLogString(final int delayTime) {
  52. Log.e("TAG", "Runnable" + delayTime);
  53. new Thread(new Runnable() {
  54. @Override
  55. public void run() {
  56. try {
  57. Thread.sleep(delayTime * 10);
  58. } catch (Exception ex) {
  59. Log.e("delayTime", ex.getMessage());
  60. }
  61. Log.e("Semaphore", "semaphore.release();");
  62. Log.e("TAG", LogString);
  63. semaphore.release();
  64. }
  65. }).start();
  66. }
  67. }

全部代码

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. 漏洞科普:对于XSS和CSRF你究竟了解多少

    转自:http://www.freebuf.com/articles/web/39234.html 随着Web2.0.社交网络.微博等等一系列新型的互联网产品的诞生,基于Web环境的互联网应用越来越广 ...

  2. Js 关于console 在IE 下的兼容问题

    程序员在开发代码的过程中,使用console作为调试代码过程的一种手段. 发布到测试生产环境,发现IE8 出现加载错误.使用开发者工具调试,发现可以绕过问题. 通过网络搜索和在项目中进行修正. 以下办 ...

  3. 制作OS X 10.9 Mavericks 安装U盘

    转载:http://www.macx.cn/forum.php?mod=viewthread&tid=2094799 安装win7的话,在mac中使用bootcamp制作一个win7安装盘即可 ...

  4. C 结构体位域

    位域 : 有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位.例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可.为了节省存储空间,并使处理简便,C语言又提供了一 ...

  5. 分享——张南《从Desktop到Mobile的自动化测试实践》

    张南在top100summit(14年)上分享了google从Desktop到Mobile的自动化测试实践,这里分享一下 案例简述 随着每年移动用户量的增长,移动网络速度以及覆盖力的增强,移动设备逐年 ...

  6. poj2486Apple Tree[树形背包!!!]

    Apple Tree Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9989   Accepted: 3324 Descri ...

  7. POJ3013 Big Christmas Tree[转换 最短路]

    Big Christmas Tree Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 23387   Accepted: 5 ...

  8. NOIP2000乘积最大[序列DP]

    题目描述 今年是国际数学联盟确定的“2000――世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年.在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友XZ也有幸得 ...

  9. jmeter的压力测试

    Apache JMeter是Apache组织开发的基于Java的压力测试工具.用于对软件做压力测试. 以下为压力测试的简单介绍 1.在测试计划下增加一个线程组 2.线程组的内容需要进行编辑,根据压力测 ...

  10. 关于Kendo UI的使用心得

    1.在筛选里面的条件选项进行编辑 filterable: { extra: false, operators: { string: { startswith: "Starts with&qu ...