最近总想总结一下消息队列相关的知识,但是首先先把消息队列的基础---生产者消费者模式来复习一下。
生产者消费者模式在操作系统及线程知识中已经讲的很多,概念不多叙述。下面引用知名培训教师马士兵的代表来简单说明一下吧。
先解释一下:wait()和notify(),notifyAll()方法
从功能上来说wait就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的notify()唤醒该线程,才能继续获取对象锁,并继续执行。相应的notify()就是对对象锁的唤醒操作。但有一点需要注意的是notify()调用后,并不是马上就释放对象锁的,而是在相应的synchronized(){}语句块执行结束,自动释放锁后,JVM会在wait()对象锁的线程中随机选取一线程,赋予其对象锁,唤醒线程,继续执行。
public class ProducerConsumer {
public static void main(String[] args) {
SyncStack ss = new SyncStack();
Producer p = new Producer(ss);
Consumer c = new Consumer(ss);
new Thread(p).start();
new Thread(c).start();
}
}
class WoTou {
int id;
WoTou(int id) {
this.id = id;
}
public String toString() {
return "WoTou : " + id;
}
}
class SyncStack {
int index = 0;
WoTou[] arrWT = new WoTou[6];
public synchronized void push(WoTou wt) {
while (index == arrWT.length) { //while循环避免异常的情况
try {
this.wait(); //当前线程处于等待状态,直到其他线程调用notify或者是notifAll来唤醒此线程
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll(); //唤醒正处于wait的线程
arrWT[index] = wt;
System.out.println("set: " + arrWT[index]);
index++;
}
public synchronized WoTou pop() {
while (index == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
index--;
System.out.println("get :" + arrWT[index]);
return arrWT[index];
}
}
class Producer implements Runnable {
SyncStack ss = null;
Producer(SyncStack ss) {
this.ss = ss;
}
public void run() {
for (int i = 0; i < 20; i++) {
WoTou wt = new WoTou(i);
ss.push(wt);
try {
Thread.sleep((int) (Math.random() * 200));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable {
SyncStack ss = null;
Consumer(SyncStack ss) {
this.ss = ss;
}
public void run() {
for (int i = 0; i < 20; i++) {
WoTou wt = ss.pop();
try {
Thread.sleep((int) (Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
上面的例子是用栈来实现的消费者生产者的模式。把栈转换成队列,自然也就形成了消息队列的雏形。队列的实现这里也不赘述了,下面几行代码给出了jdk当中队列的实现。
int time = 10;
Queue<Integer> queue = new LinkedList<Integer>();
for (int i = time; i >= 0; i--)
queue.add(i);
while(!queue.isEmpty()) {
System.out.println(queue.remove());
Thread.sleep(1000);
}