Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android編程入門 >> Android中的Semaphore

Android中的Semaphore

編輯:Android編程入門

信號量,了解過操作系統的人都知道,信號量是用來做什麼的···

在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();
     }
 }
全部代碼
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved