• Android中的Semaphore


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

    在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     }

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

    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来解决这个问题:

    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     }

    日志如下:

    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代码,再来测试看看。

     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     }

    然后看看日志:

    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是不会执行的。需要特别留意。

    下面是全部的代码:

     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 
    13 public class MainActivity extends AppCompatActivity {
    14 
    15     private String LogString;
    16 
    17     @Override
    18     protected void onCreate(Bundle savedInstanceState) {
    19         super.onCreate(savedInstanceState);
    20         setContentView(R.layout.activity_main);
    21         Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    22         setSupportActionBar(toolbar);
    23 
    24         FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    25         fab.setOnClickListener(onClickListener);
    26     }
    27 
    28     View.OnClickListener onClickListener = new View.OnClickListener() {
    29         @Override
    30         public void onClick(View v) {
    31             Log.e("Semaphore", "semaphore.release();");
    32             semaphore.release();
    33             Start();
    34         }
    35     };
    36 
    37     private final Semaphore semaphore = new Semaphore(0, true);
    38 
    39     private void Start() {
    40         for (int i = 10; i >= 0; i--) {
    41             try {
    42                 Log.e("Semaphore", "semaphore.acquire();" + i);
    43                 semaphore.acquire();
    44             } catch (Exception ex) {
    45                 Log.e("Semaphore", ex.getMessage());
    46             }
    47             LogString = "num:" + i;
    48             printLogString(i);
    49         }
    50     }
    51 
    52     private void printLogString(final int delayTime) {
    53         Log.e("TAG", "Runnable" + delayTime);
    54         new Thread(new Runnable() {
    55             @Override
    56             public void run() {
    57                 try {
    58                     Thread.sleep(delayTime * 10);
    59                 } catch (Exception ex) {
    60                     Log.e("delayTime", ex.getMessage());
    61                 }
    62                 Log.e("Semaphore", "semaphore.release();");
    63                 Log.e("TAG", LogString);
    64                 semaphore.release();
    65             }
    66         }).start();
    67     }
    68 }
    全部代码
  • 相关阅读:
    ps
    Elasticsearch Java Rest Client API 整理总结 (一)
    "error" : "Content-Type header [application/x-www-form-urlencoded] is not supported"
    hdu1421 搬寝室(dp)
    A题之变态青蛙跳
    11.Laravel5学习笔记:扩展 Validator 类
    HDU 5607 graph(矩阵优化+概率DP)
    《Spring技术内幕》笔记-Spring的设计理念和总体架构
    hihocoder 1124 : 好矩阵 dp
    关于ValueAnimation以及Interpolator +Drawable实现的自己定义动画效果
  • 原文地址:https://www.cnblogs.com/maomishen/p/5350052.html
Copyright © 2020-2023  润新知