在上文"浅谈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,会经常碰到类似的应用,想了解它,还是自己编个小程序,做测试吧,相信会有所收获!
分享到:
相关推荐
Java同步与异步 Java同步与异步是Java编程中非常重要的概念,它们都是为了解决多线程环境中的线程安全问题。在多线程环境中,如果没有正确的同步机制,多个线程可能会同时访问共享资源,导致数据不一致和其他严重...
PPT中介绍了在Java语言中加入乐观锁从而提高性能的一种方法。 Android的Dalvik和ART虚拟机中的锁都是采用了这种方式。
乐观锁适用于多读的应用类型,这样可以提高吞吐量,在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS(Compare and Swap 比较并交换)实现的。 悲观锁:总是假设最坏的情况,...
java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 ...
Java多线程同步机制在实际应用中有很多应用,例如: * 在线银行系统中,使用Java多线程同步机制来确保多个用户同时访问同一个账户的正确执行。 * 在社交媒体平台中,使用Java多线程同步机制来确保多个用户同时发布...
Java同步与异步 Java 同步与异步是一种编程技术,旨在解决多线程环境下的数据一致性和可见性问题。下面是 Java 同步与异步的定义和概念: 关键字: * thread(线程):Java 中的基本执行单元,能够独立执行一...
java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 JAR ...
java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 JAR ...
java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 ...
本版本还增加了广泛的例子,展示如何实现线程池和其他同步技术,如条件变量、屏障和守护锁。它展示了如何与非线程安全的类共同工作,并特别关注于Swing的线程问题。新增加的一章介绍了如何为多处理器机器编写并行...
java并发库thread使用,传统线程技术、定时器技术、线程互斥技术,同步通讯技术、多线程共享数据、并发库应用,线程锁技术,阻塞锁、阻塞队列,线程池等应用
Java面试通常涵盖多个...并发编程:了解Java中的线程、同步、锁等机制,以及Java并发包中的工具类。 JVM与性能调优:对Java虚拟机(JVM)有一定了解,包括内存管理、垃圾回收等方面,并知道如何进行基本的性能调优。
1 6一个简单的Java小应用程序 1 7什么是JSP 习题 第2章标识符 关键字和数据类型 2 1标识符和关键字 2 2Java的基本数据类型 2 3Java的数组 习题 第3章运算符 表达式和语句 3 1运算符与表达式 3 2语句概述 3 3控制语句...
032003_【第20章:Java新IO】_文件锁笔记.pdf 032004_【第20章:Java新IO】_字符集笔记.pdf 032005_【第20章:Java新IO】_Selector笔记.pdf 042101_【课程讲解】_附录:Eclipse开发工具笔记.pdf 050101_〖开发实例〗...
java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 ...
15 applet java可以编写两类程序,applications和applet,applications可以在控制台直接运行,与其他高级编程语言没有太大区别,而java的特色在于它具有编制小应用程序的功能,applet可以在internet上传输并在兼容...
介绍了如何使用类库提供的基本并发构建块,用于避免并发危险、构造线程安全的类及验证线程安全的规则,如何将小的线程安全类组合成更大的线程安全类,如何利用线程来提高并发应用程序的吞吐量,如何识别可并行执行的任务...
java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 ...