注:本程序来自于《Java面向对象程序设计基础教程》冯洪海主编中的线程同步例子,我加上了一些注释,仅学习之用,欢迎指正。
记得wait()和notify()必须成对出现,否则会出现死锁。
Buffer.java
package lgw.util;
public class Buffer {
private char chBuffer;
private boolean empty = true; //信号量
//往缓冲区放入资源
public synchronized void put(char ch) {
//P操作
while(!this.empty) { //缓冲区不空,无法放入资源
try {
wait(); //其他线程(生产者线程)等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.chBuffer = ch;
this.empty = false; //缓冲区标识为不空
notify(); //V操作,通知其他线程(消费者线程)空闲
}
//从缓冲区中获取资源
public synchronized char get() {
//P操作
while(this.empty) { //缓冲区为空,无法获取资源
try {
wait(); //其他线程(消费者线程)等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
char ch = this.chBuffer; //获得资源(字符)
this.chBuffer = '\0'; //资源重置
this.empty = true; //缓冲区标识为空
notify(); //V操作,通知其他线程(生产者线程)空闲
return ch; //返回资源给调用者
}
}
Consumer.java
package lgw;
import lgw.util.Buffer;
//消费者线程,是线程类的子类
public class Consumer extends Thread {
private Buffer br; //消费者拥有缓冲区,消费缓冲区的资源
public Consumer(Buffer br) { //构造方法
this.br = br;
}
@SuppressWarnings("static-access")
public void run() {
for(int i=1; i<=5; i++) { //当前消费者线程共消费5个资源
System.out.println("hello,Consumer!");
synchronized (br) { //缓冲区需要同步操作
char ch = br.get(); //从缓冲区中取出资源(字符)
if(ch != '\0') {
System.out.println("消费者" + i + "消费了产品:" + ch);
} else {
System.out.println("消费者" + i + "没有产品可以消费");
}
}
try {
this.sleep(50); //消费1个资源后消费者线程休眠50毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Procedure.java
package lgw;
import java.util.Random;
import lgw.util.Buffer;
//生产者线程
public class Procedure extends Thread {
private Buffer br; //生产者拥有缓冲区,生产者生产资源放入缓冲区
Random r = new Random(); //随机数类实例r用来产生随机数
public Procedure(Buffer br) { //构造方法
this.br = br;
}
@SuppressWarnings("static-access")
public void run() {
for(int i=1; i<=5; i++){ //消费者线程共消费5个资源
System.out.println("hello,Procedure!");
char ch = (char)(65 + r.nextInt(20)); //产生A~T的随机字符
br.put(ch); //资源放入缓冲区
System.out.println("生产者" + i + "生产了产品:" + ch);
try {
this.sleep(5);
} catch(InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
Test.java
package lgw;
import lgw.util.Buffer;
public class Test {
public static void main(String args[]) {
Buffer buffer = new Buffer(); //创建缓冲区buffer
Procedure p = new Procedure(buffer); //用buffer初始化生产者
Consumer c = new Consumer(buffer); //用buffer初始化消费者
p.start(); //生产者开始生产
c.start(); //消费者开始消费
}
}
运行结果:
hello,Consumer!
hello,Procedure!
生产者1生产了产品:Q
消费者1消费了产品:Q
hello,Procedure!
生产者2生产了产品:O
hello,Procedure!
hello,Consumer!
消费者2消费了产品:O
生产者3生产了产品:N
hello,Procedure!
hello,Consumer!
消费者3消费了产品:N
生产者4生产了产品:T
hello,Procedure!
hello,Consumer!
消费者4消费了产品:T
生产者5生产了产品:A
hello,Consumer!
消费者5消费了产品:A
附: