热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android多线程之同步锁的使用

本文主要介绍了Android多线程之同步锁的使用,分享给大家,具体如下: 一、同步机制关键字synchronized 对于Java

本文主要介绍了Android多线程之同步锁的使用,分享给大家,具体如下:

一、同步机制关键字synchronized

对于Java来说,最常用的同步机制就是synchronized关键字,他是一种基于语言的粗略锁,能够作用于对象、函数、class。每个对象都只有一个锁,谁能够拿到这个锁谁就有访问权限。当synchronized作用于函数时,实际上锁的也是对象,锁定的对象就是该函数所在类的对象。而synchronized作用于class时则是锁的这个Class类,并非具体对象。

public class SynchronizedClass {
  public synchronized void syncMethod(){
    //代码
  }

  public void syncThis(){
    synchronized (this){
      //代码
    }
  }

  public void syncClassMethod(){
    synchronized (SynchronizedClass.class){
      //代码
    }
  }

  public synchronized static void syncStaticMethod(){
    //代码
  }
}

上面演示了同步方法、同步块、同步class对象、同步静态方法。前2种锁的是对象,而后两种锁的是class对象。对于class对象来说,它的作用是防止多个线程同时访问添加了synchronized锁的代码块,而synchronized作用于引用对象是防止其他线程访问同一个对象中synchronized代码块或者函数。

二、显示锁———-ReentrankLock和Condition

ReentrankLock 和内置锁synchronized相比,实现了相同的语义,但是更具有更高的灵活性。

(1)获得和释放的灵活性。
(2)轮训锁和定时锁。
(3)公平性。

基本操作:

lock(): 获取锁

tryLock(): 尝试获取锁

tryLock(long timeout,TimeUnit unit): 尝试获取锁,如果到了指定的时间还获取不到,那么超时。

unlock(): 释放锁

newCondition(): 获取锁的 Condition

使用ReentrantLock的一般组合是 lock、tryLock、与unLock成对出现,需要注意的是,千万不要忘记调用unlock来释放锁,负责可能引发死锁的问题。ReentrantLock的常用形式如下所示:

public class ReentrantLockDemo {
  Lock lock = new ReentrantLock();

  public void doSth(){
    lock.lock();
    try {
      //执行某些操作
    }finally {
      lock.unlock();
    }
  }
}

需要注意的是,lock必须在finally开中释放,否则,如果受保护的代码抛出异常,锁就可能永远得不到释放!!

ReentrantLock类中还有一个重要的函数newCondition(),该函数用户获取Lock()上的一个条件,也就是说Condition与Lock绑定。Condition用于实现线程间的通信,他是为了解决Object.wait(),nofity(),nofityAll() 难以使用的问题。
Condition的方法如下:

await() : 线程等待

await(int time,TimeUnit unit) 线程等待特定的时间,超过的时间则为超时。

signal() 随机唤醒某个等待线程

signal() 唤醒所有等待中的线程

示例代码:

public class MyArrayBlockingQueue {

//  数据数组
  private final T[] items;

  private final Lock lock = new ReentrantLock();

  private Condition notFull = lock.newCondition();
  private Condition notEmpty = lock.newCondition() ;

//  头部索引
  private int head;
//  尾部索引
  private int tail ;
//  数据的个数
  private int count;

  public MyArrayBlockingQueue(int maxSize) {
    items = (T[]) new Object[maxSize];
  }

  public MyArrayBlockingQueue(){
    this(10);
  }

  public void put(T t){
    lock.lock();
    try {
      while(count == getCapacity()){
        System.out.println("数据已满,等待");
        notFull.await();
      }
      items[tail] =t ;
      if(++tail ==getCapacity()){
        tail = 0;
      }
      ++count;
      notEmpty.signalAll();//唤醒等待数据的线程
    } catch (InterruptedException e) {
      e.printStackTrace();
    }finally {
      lock.unlock();
    }
  }

  public int getCapacity(){
    return items.length ;
  }

  public T take(){
    lock.lock();
    try {
      while(count ==0){
        System.out.println("还没有数据,等待");
        //哪个线程调用await()则阻塞哪个线程
        notEmpty.await();
      }
      T ret = items[head];
      items[head] = null ;
      if(++head == getCapacity()){
        head =0 ;
      }
      --count;
      notFull.signalAll();
      return ret ;
    } catch (InterruptedException e) {
      e.printStackTrace();
    }finally {
      lock.unlock();
    }
    return null ;
  }

  public int size(){
    lock.lock();
    try {
      return count;
    }finally {
      lock.unlock();
    }
  }

  public static void main(String[] args){
    MyArrayBlockingQueue aQueue = new MyArrayBlockingQueue<>();
    aQueue.put(3);
    aQueue.put(24);
    for(int i=0;i<5;i++){
      System.out.println(aQueue.take());
    }

    System.out.println("结束");
  }
}

执行结果:

3
24
还没有数据,等待

三、信号量 Semaphore

Semaphore是一个计数信号量,它的本质是一个“共享锁”。信号量维护了一个信号量许可集,线程可以通过调用acquire()来获取信号量的许可。当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到可用的许可为止。线程可以通过release()来释放它所持有的信号量许可。

示例:

public class SemaphoreTest {
  public static void main(String[] args){
    final ExecutorService executorService = Executors.newFixedThreadPool(3);
    final Semaphore semaphore = new Semaphore(3);
    List futures = new ArrayList<>();
    for (int i = 0; i <5; i++) {
      Future<&#63;> submit = executorService.submit(new Runnable() {
        @Override
        public void run() {
          try {
            semaphore.acquire();
            System.out.println(" 剩余许可: " + semaphore.availablePermits());
            Thread.sleep(3000);
            semaphore.release();
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      });
      futures.add(submit);
    }
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 如何清除Chrome浏览器地址栏的特定历史记录
    在使用Chrome浏览器时,你可能会发现地址栏保存了大量浏览记录。有时你可能希望删除某些特定的历史记录而不影响其他数据。本文将详细介绍如何单独删除地址栏中的特定记录以及批量清除所有历史记录的方法。 ... [详细]
  • 利用Selenium与ChromeDriver实现豆瓣网页全屏截图
    本文介绍了一种使用Selenium和ChromeDriver结合Python代码,轻松实现对豆瓣网站进行完整页面截图的方法。该方法不仅简单易行,而且解决了新版Selenium不再支持PhantomJS的问题。 ... [详细]
  • 鼠标悬停出现提示信息怎么做
    概述–提示:指启示,提起注意或给予提醒和解释。在excel中会经常用到给某个格子增加提醒信息,比如金额提示输入数值或最大长度值等等。设置方式也有多种,简单的,仅为单元格插入批注就可 ... [详细]
  • 本文将详细介绍多个流行的 Android 视频处理开源框架,包括 ijkplayer、FFmpeg、Vitamio、ExoPlayer 等。每个框架都有其独特的优势和应用场景,帮助开发者更高效地进行视频处理和播放。 ... [详细]
  • 气象对比分析
    本文探讨了不同地区和时间段的天气模式,通过详细的图表和数据分析,揭示了气候变化的趋势及其对环境和社会的影响。 ... [详细]
  • 本文探讨了如何利用NFC技术,将存储在Android手机中的患者信息安全高效地传输到台式计算机。重点介绍了适用于医院场景的NFC USB读卡器(如ACR122U)的应用方法。 ... [详细]
  • 探讨 HDU 1536 题目,即 S-Nim 游戏的博弈策略。通过 SG 函数分析游戏胜负的关键,并介绍如何编程实现解决方案。 ... [详细]
  • 本文回顾了2017年的转型和2018年的收获,分享了几家知名互联网公司提供的工作机会及面试体验。 ... [详细]
  • 深入解析动态代理模式:23种设计模式之三
    在设计模式中,动态代理模式是应用最为广泛的一种代理模式。它允许我们在运行时动态创建代理对象,并在调用方法时进行增强处理。本文将详细介绍动态代理的实现机制及其应用场景。 ... [详细]
  • 深入理解ExtJS:从入门到精通
    本文详细介绍了ExtJS的功能及其在大型企业前端开发中的应用。通过实例和详细的文件结构解析,帮助初学者快速掌握ExtJS的核心概念,并提供实用技巧和最佳实践。 ... [详细]
  • Python中HOG图像特征提取与应用
    本文介绍如何在Python中使用HOG(Histogram of Oriented Gradients)算法进行图像特征提取,探讨其在目标检测中的应用,并详细解释实现步骤。 ... [详细]
  • 通常情况下,修改my.cnf配置文件后需要重启MySQL服务才能使新参数生效。然而,通过特定命令可以在不重启服务的情况下实现配置的即时更新。本文将详细介绍如何在线调整MySQL配置,并验证其有效性。 ... [详细]
  • Android 6.0 切换指定 Wi-Fi 的解决方案
    本文详细介绍了在 Android 6.0 系统中切换到指定 Wi-Fi 的方法,包括常见的问题、原因分析及解决方案。通过官方文档和代码示例,帮助开发者更好地理解和实现这一功能。 ... [详细]
  • vivo Y5s配备了联发科Helio P65八核处理器,这款处理器采用12纳米工艺制造,具备两颗高性能Cortex-A75核心和六颗高效能Cortex-A55核心。此外,它还集成了先进的图像处理单元和语音唤醒功能,为用户提供卓越的性能体验。 ... [详细]
  • 深入解析 Android IPC 中的 Messenger 机制
    本文详细介绍了 Android 中基于消息传递的进程间通信(IPC)机制——Messenger。通过实例和源码分析,帮助开发者更好地理解和使用这一高效的通信工具。 ... [详细]
author-avatar
浩哥
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有