`

Java同步锁之小应用

 
阅读更多

只对同步锁的相关概念做了简单阐述,没给出应用实例。本文,将结合现实中对于同步锁的需求,编个小例子。标题比较大,而实例并不一定十分恰当,请各位见谅。

 

需求: 一个消费者在不停的从queue里取消息,当没有消息时,阻塞等待,直到有消息来时,消费它。

 

简析: 乍一看,我们完全可以写个循环不断的去读它(queue),直到该queue不再empty,则消费一条消息(ps: 设个标志位, 循环去读,同理)。可是,无限的循环不仅有可能浪费资源,而且如果额外想设个timeout的话,还要多写好多代码,如需要取当前时间,进行比对等等。这时,如果我们使用wait()或wait(int timeout)让其阻塞等待,直到有其他线程执行了notify(),则可以让问题迎刃而解。

 

废话不多说,首先是我们的Consumer类。

 

Java代码  收藏代码
  1. import java.util.LinkedList;  
  2.   
  3. /** 
  4.  * Consumer. <BR> 
  5.  *  
  6.  * @author Michael Ma 
  7.  * @version 1.0.0 
  8.  */  
  9. public class Consumer {  
  10.     /** A lock object */  
  11.     private final Object lock;  
  12.     /**queue of message */  
  13.     private LinkedList<Object> msgQueue = new LinkedList<Object>();  
  14.     /** CLOSED message */  
  15.     public static final Object CLOSED = new Object();  
  16.       
  17.     /** 
  18.      * 构造函数. <BR> 
  19.      * lock指向this指针 
  20.      * 
  21.      */  
  22.     public Consumer() {  
  23.         this.lock = this;  
  24.     }  
  25.       
  26.     /** 
  27.      * 开始消费. 如果queue中没有消息,则阻塞 <BR> 
  28.      * 
  29.      * @return this 
  30.      */  
  31.     public Consumer startConsume() {  
  32.         synchronized (lock) {  
  33.             try {  
  34.                 if (!msgQueue.isEmpty()) {  
  35.                     return this;  
  36.                 }  
  37.                   
  38.                 // 将timeout设为10秒  
  39.                 lock.wait(10000);  
  40.             } catch (InterruptedException e) {  
  41.                 e.printStackTrace();  
  42.             }  
  43.         }  
  44.           
  45.         return this;  
  46.     }  
  47.       
  48.     /** 
  49.      * 从queue中读消息 <BR> 
  50.      *  
  51.      * @return message content 
  52.      * @throws Exception e 
  53.      */  
  54.     public Object getMessage() throws Exception{  
  55.         synchronized (lock) {  
  56.             // 从queue中取一条消息  
  57.             Object message = msgQueue.poll();  
  58.   
  59.             // 若该消息为Error, 抛出  
  60.             if (message instanceof Exception) {  
  61.                 throw (Exception) message;  
  62.             }  
  63.               
  64.             // 返回null如果接到CLOSED消息,或message本身为空  
  65.             if (message == null  
  66.                     || message == CLOSED) {  
  67.                 return null;  
  68.             }  
  69.               
  70.             return message;  
  71.         }  
  72.     }  
  73.       
  74.     /** 
  75.      * 向Queue里添加消息, notfify等待中的线程 <BR> 
  76.      * 
  77.      * @param message Object 
  78.      */  
  79.     public void setMessage(Object message) {  
  80.         synchronized (lock) {  
  81.             // 向Queue中添加消息  
  82.             msgQueue.add(message);  
  83.               
  84.             // notify等待中的线程  
  85.             lock.notify();  
  86.         }  
  87.     }  
  88.       
  89.     /** 
  90.      * 关闭消息 <BR> 
  91.      */  
  92.     public void setClosed() {  
  93.         setMessage(CLOSED);  
  94.     }  
  95. }  

 测试类, 比较简单,就不加注释啦 

 

Java代码  收藏代码
  1. public class ConsumerTest extends Thread {  
  2.     Consumer c = null;  
  3.       
  4.     public ConsumerTest(Consumer c) {  
  5.         this.c = c;  
  6.     }  
  7.       
  8.     public static void main(String[] args) throws Exception {  
  9.         Consumer c = new Consumer();  
  10.         // 开一个线程,去往queue里添加消息  
  11.         ConsumerTest test = new ConsumerTest(c);  
  12.         test.start();  
  13.         Object msg;  
  14.         while ((msg = c.startConsume().getMessage()) != null) {  
  15.             System.out.println(msg);  
  16.         }  
  17.     }  
  18.       
  19.     public void run() {  
  20.         try {  
  21.             sleep(3000);  
  22.             c.setMessage(new String("abc"));  
  23.             sleep(2000);  
  24.             c.setMessage(new String("def"));  
  25.             c.setMessage(Consumer.CLOSED);  
  26.         } catch (InterruptedException e) {  
  27.             e.printStackTrace();  
  28.         }  
  29.     }  
  30. }  

 

小结: 开始编这个例子时,还是挺容犯些小错误的。

1. 首先应该注意synchronized的对象,和wait,notify的对象,是不是相同的, 否则会报llegalMonitorStateException异常。 (解释请参考上文)。 

2. 各不同线程操作的对象是不是一个,若notify该类的其他对象则是没用的,当然,如果该类被设计为单体类,就没有这个后顾之忧啦。

3. notifyAll是唤醒在该对象上所有在waiting中的线程,适当场合时应用。(例如一个公告牌,很多线程都在等最新的消息,当公告消息来时,唤醒所有读它的线程。)

分享到:
评论

相关推荐

    支持10000同步锁,Spring Boot,Java

    文件名`java_demo_synchronized`可能包含的是关于Java同步锁的示例代码,可以从中学习如何在实际项目中应用同步锁策略。通过深入理解同步锁的工作原理和优化技巧,我们可以构建出高效、高并发的Spring Boot应用程序...

    Java 同步锁 wait notify 学习心得

    ### Java同步锁原理 在Java中,`synchronized`关键字用于实现线程同步,即确保同一时刻只有一个线程可以访问特定的代码块或方法。这种机制通过内部维护一个锁来实现,每个对象都有一个内置锁,这个锁可以被任何拥有...

    java编程的生产者消费者同步锁线程测试

    在Java编程中,多线程是...总之,掌握Java的线程同步锁,理解生产者消费者问题及其解决策略,是成为一名合格的Java开发者所必需的技能。通过实际的编程练习,你可以更好地领会这些概念,并运用到实际的并发应用程序中。

    java同步锁的正确使用方法(必看篇)

    Java 同步锁的正确使用方法 Java 同步锁是 Java 编程语言中的一种机制,用于解决多线程环境下的线程安全问题。正确使用同步锁可以确保多线程环境下的数据安全和线程安全。 同步锁的分类 ------------ 同步锁有三...

    spring实现集群同步锁

    Spring作为一款广泛使用的Java应用框架,提供了多种方式来实现集群同步锁。本篇文章将深入探讨如何利用Spring在集群环境中实现同步锁,并以Redis作为分布式锁的存储媒介进行实践。 首先,我们要理解什么是集群同步...

    基于Java synchronized同步锁实现线程交互.pdf

    "基于Java synchronized同步锁实现线程交互" Java多线程能够提高CPU利用效率,但也容易造成线程不安全、线程死锁等问题。Java synchronized同步锁可以保证同一时刻只有一个线程操作同一资源,使用wait()、notify()...

    Java中瘦锁的应用

    根据文件内容,本文将主要探讨在Java中应用所谓的“瘦锁(Thin Locks)”技术,以及这种技术在Android Dalvik和ART虚拟机中的应用。 首先,让我们了解瘦锁的概念。在Java中,锁通常用于保证多线程环境下的数据一致...

    java锁机制Synchronizedjava锁机制Synchronized

    Java 锁机制 Synchronized 是 Java 语言中的一种同步机制,用于解决多线程并发访问共享资源时可能出现的一些问题。 Java 锁机制 Synchronized 的概念 在 Java 中,每个对象都可以被看作是一个大房子,其中有多个...

    java锁详解.pdf

    Java 锁详解 Java 锁是 Java 并发编程中的一种基本机制,用于确保线程安全和避免竞争条件。Java 锁可以分为两大类:synchronized 锁和 ReentrantLock 锁。 一、Synchronized 锁 1. 锁的原理:synchronized 锁是...

    层次业务模型的同步锁设计

    Java中常见的同步锁有synchronized关键字、ReentrantLock(可重入锁)、ReadWriteLock(读写锁)等。synchronized是内置的、隐式的锁,而ReentrantLock和ReadWriteLock属于显式锁,提供了更细粒度的控制和更丰富的...

    解析Java线程同步锁的选择方法

    选择哪种同步锁主要取决于应用场景的需求。如果简单同步即可满足,使用`synchronized`关键字是最简单的选择。对于更复杂的同步需求,如需要更精细的控制、更高的性能或者可中断/定时的等待,Lock接口及其实现更适合...

    Java同步机制浅谈

    ### Java同步机制浅谈 #### synchronized关键字的作用及应用 在Java多线程环境中,`synchronized`关键字扮演着至关重要的角色。它可以帮助开发者确保多线程环境下的数据一致性,防止因并发访问导致的数据错误。本...

    redis同步锁AOP实现

    通过这种方式,我们可以轻松地在整个应用中添加Redis同步锁,而无需在每个方法中手动处理锁的获取和释放,提高了代码的可读性和维护性。 此外,还可以考虑以下优化点: - 锁的公平性:默认情况下,Redisson的锁是非...

    彻底理解Java中的各种锁.pdf

    Java是一种广泛使用的编程语言,它在处理多线程环境下的数据同步和并发控制时,提供了多种锁机制来保证数据的一致性和线程的安全。本文将详细介绍Java中包括乐观锁、悲观锁、自旋锁、可重入锁、读写锁等多种锁机制的...

    java同步、异步相关知识点

    `synchronized`关键字是最常用的同步机制之一。它可以用来修饰方法或者代码块,确保同一时刻只有一个线程能够访问被修饰的资源。 - **修饰方法**:当`synchronized`用于修饰一个实例方法时,该锁的范围是整个对象;...

    java同步synchronized关键字用法示例

    Java中的`synchronized`关键字是多线程编程中的一个重要概念,用于控制并发访问共享资源时的同步机制。在Java中,当多个线程试图同时访问和修改同一块代码或数据时,可能会导致数据不一致的问题。为了解决这个问题,...

    java锁的释放与建立

    本篇文章将深入探讨Java锁的释放与建立,以及它们之间的_happens-before_关系,旨在帮助开发者更好地理解和应用并发控制。 首先,Java中的锁主要包括两种类型:内置锁(也称为监视器锁)和显式锁。内置锁是通过`...

    Java的锁机制的学习和使用

    ### Java的锁机制详解 #### 一、Java锁机制概览 Java中的锁机制主要用于解决多线程环境下的资源竞争问题。在并发编程中,为了保证数据一致性与正确性,通常需要采用各种锁来控制对共享资源的访问。Java语言提供了...

    java 线程同步 信号量控制同步

    锁可以是对象锁、类锁或同步锁。锁的作用是防止多个线程同时访问同一个共享资源,避免资源冲突和数据不一致。 信号量机制是 Java 中的一种线程同步机制。信号量是一个整数值,表示当前可用的资源数量。线程可以通过...

    java 同步方法

    【Java 同步方法】是Java编程中...总之,理解和优化Java同步方法的使用,是提高多线程应用程序性能和可伸缩性的核心。通过精细调整同步策略,可以有效地减少争用,提升并发性能,从而让程序在高负载环境下表现更佳。

Global site tag (gtag.js) - Google Analytics