`

Java同步锁之小应用

    博客分类:
  • Java
阅读更多

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

 

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

 

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

 

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

 

import java.util.LinkedList;

/**
 * Consumer. <BR>
 * 
 * @author Michael Ma
 * @version 1.0.0
 */
public class Consumer {
	/** A lock object */
	private final Object lock;
	/**queue of message */
	private LinkedList<Object> msgQueue = new LinkedList<Object>();
	/** CLOSED message */
	public static final Object CLOSED = new Object();
	
	/**
	 * 构造函数. <BR>
	 * lock指向this指针
	 *
	 */
	public Consumer() {
		this.lock = this;
	}
	
	/**
	 * 开始消费. 如果queue中没有消息,则阻塞 <BR>
	 *
	 * @return this
	 */
	public Consumer startConsume() {
		synchronized (lock) {
			try {
				if (!msgQueue.isEmpty()) {
					return this;
				}
				
				// 将timeout设为10秒
				lock.wait(10000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		return this;
	}
	
	/**
	 * 从queue中读消息 <BR>
	 * 
	 * @return message content
	 * @throws Exception e
	 */
	public Object getMessage() throws Exception{
		synchronized (lock) {
			// 从queue中取一条消息
			Object message = msgQueue.poll();

			// 若该消息为Error, 抛出
			if (message instanceof Exception) {
                throw (Exception) message;
            }
			
			// 返回null如果接到CLOSED消息,或message本身为空
			if (message == null
					|| message == CLOSED) {
				return null;
			}
			
			return message;
		}
	}
	
	/**
	 * 向Queue里添加消息, notfify等待中的线程 <BR>
	 *
	 * @param message Object
	 */
	public void setMessage(Object message) {
		synchronized (lock) {
			// 向Queue中添加消息
			msgQueue.add(message);
			
			// notify等待中的线程
			lock.notify();
		}
	}
	
	/**
	 * 关闭消息 <BR>
	 */
	public void setClosed() {
		setMessage(CLOSED);
    }
}

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

 

public class ConsumerTest extends Thread {
	Consumer c = null;
	
	public ConsumerTest(Consumer c) {
		this.c = c;
	}
	
	public static void main(String[] args) throws Exception {
		Consumer c = new Consumer();
		// 开一个线程,去往queue里添加消息
		ConsumerTest test = new ConsumerTest(c);
		test.start();
		Object msg;
		while ((msg = c.startConsume().getMessage()) != null) {
			System.out.println(msg);
		}
	}
	
	public void run() {
		try {
			sleep(3000);
			c.setMessage(new String("abc"));
			sleep(2000);
			c.setMessage(new String("def"));
			c.setMessage(Consumer.CLOSED);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

 

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

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

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

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

 

* 题外话: 在Java和其他一些开源项目中,如Mina,会经常碰到类似的应用,想了解它,还是自己编个小程序,做测试吧,相信会有所收获!

2
2
分享到:
评论

相关推荐

    Java同步与异步.pdf

    Java同步与异步 Java同步与异步是Java编程中非常重要的概念,它们都是为了解决多线程环境中的线程安全问题。在多线程环境中,如果没有正确的同步机制,多个线程可能会同时访问共享资源,导致数据不一致和其他严重...

    Java中瘦锁的应用

    PPT中介绍了在Java语言中加入乐观锁从而提高性能的一种方法。 Android的Dalvik和ART虚拟机中的锁都是采用了这种方式。

    Java中的锁分类与使用.docx

    乐观锁适用于多读的应用类型,这样可以提高吞吐量,在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS(Compare and Swap 比较并交换)实现的。 悲观锁:总是假设最坏的情况,...

    JAVA_API1.6文档(中文)

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 ...

    Java多线程同步.pdf

    Java多线程同步机制在实际应用中有很多应用,例如: * 在线银行系统中,使用Java多线程同步机制来确保多个用户同时访问同一个账户的正确执行。 * 在社交媒体平台中,使用Java多线程同步机制来确保多个用户同时发布...

    Java同步与异步[定义].pdf

    Java同步与异步 Java 同步与异步是一种编程技术,旨在解决多线程环境下的数据一致性和可见性问题。下面是 Java 同步与异步的定义和概念: 关键字: * thread(线程):Java 中的基本执行单元,能够独立执行一...

    Java 1.6 API 中文 New

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 JAR ...

    java api最新7.0

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 JAR ...

    JavaAPI1.6中文chm文档 part1

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 ...

    线程 JAVA java线程 java线程第3版 java线程第2版第3版合集

    本版本还增加了广泛的例子,展示如何实现线程池和其他同步技术,如条件变量、屏障和守护锁。它展示了如何与非线程安全的类共同工作,并特别关注于Swing的线程问题。新增加的一章介绍了如何为多处理器机器编写并行...

    java并发库高级应用源码--张孝祥

    java并发库thread使用,传统线程技术、定时器技术、线程互斥技术,同步通讯技术、多线程共享数据、并发库应用,线程锁技术,阻塞锁、阻塞队列,线程池等应用

    Java面试题合集最新版2024.zip

    Java面试通常涵盖多个...并发编程:了解Java中的线程、同步、锁等机制,以及Java并发包中的工具类。 JVM与性能调优:对Java虚拟机(JVM)有一定了解,包括内存管理、垃圾回收等方面,并知道如何进行基本的性能调优。

    Java2实用教程.rar

    1 6一个简单的Java小应用程序 1 7什么是JSP 习题 第2章标识符 关键字和数据类型 2 1标识符和关键字 2 2Java的基本数据类型 2 3Java的数组 习题 第3章运算符 表达式和语句 3 1运算符与表达式 3 2语句概述 3 3控制语句...

    Java开发详解.zip

    032003_【第20章:Java新IO】_文件锁笔记.pdf 032004_【第20章:Java新IO】_字符集笔记.pdf 032005_【第20章:Java新IO】_Selector笔记.pdf 042101_【课程讲解】_附录:Eclipse开发工具笔记.pdf 050101_〖开发实例〗...

    JavaAPI中文chm文档 part2

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 ...

    java jdk实列宝典 光盘源代码

    15 applet java可以编写两类程序,applications和applet,applications可以在控制台直接运行,与其他高级编程语言没有太大区别,而java的特色在于它具有编制小应用程序的功能,applet可以在internet上传输并在兼容...

    JAVA并发编程实践 .pdf

    介绍了如何使用类库提供的基本并发构建块,用于避免并发危险、构造线程安全的类及验证线程安全的规则,如何将小的线程安全类组合成更大的线程安全类,如何利用线程来提高并发应用程序的吞吐量,如何识别可并行执行的任务...

    java jdk-api-1.6 中文 chmd

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 ...

Global site tag (gtag.js) - Google Analytics