该小项目有6个类,如下:
Container.class
容纳生产者生产的消息,包含3个方法,往等待消费队列里面添加add(),取出pop()消息,获取消息的数量size(),这三个方法都是同步方法
AddService.class入队列方法类
AddValueThread.class:入队列线程类
PopService.class:出队列方法类
PopValueThread.class:出队列线程类
Test.class.class:测试类
项目代码:
Container.class
public class Container {
private static List list = new LinkedList();
synchronized public void add() {
if (size() < 30) {
list.add("1");
System.out.println("线程:"+Thread.currentThread().getName()+
"执行 add() 方法,size大小为:"+size());
}
}
synchronized public int size() {
return list.size();
}
synchronized public Object pop() {
Object value = list.remove(0);
System.out.println("线程:"+Thread.currentThread().getName()+"执行" +
"popFirst()方法,size大小为:"+size());
return value;
}
}
AddService.class
public class AddService {
private Container container;
public AddService(Container container) {
this.container = container;
}
public void addMethod() {
try {
synchronized (container) {
while (container.size() == 30) {
System.out.println("容器已满");
container.notifyAll();
container.wait();
}
}
Thread.sleep(500);
container.add();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
AddValueThread.class
public class AddValueThread extends Thread {
private AddService addService;
public AddValueThread(AddService addService) {
this.addService = addService;
}
@Override
public void run() {
while (true) {
addService.addMethod();
}
}
}
PopService.class
public class PopService {
private Container container;
public PopService(Container container) {
this.container = container;
}
public void popMethod() {
try {
synchronized (container) {
while (container.size() == 0) {
System.out.println("队列空");
container.notifyAll();
container.wait();
}
container.pop();
}
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
PopValueThread.class
public class PopValueThread extends Thread{
private PopService service;
public PopValueThread(PopService service) {
this.service = service;
}
@Override
public void run() {
while (true) {
service.popMethod();
}
}
}
Test.class.class
public class Test {
public static void main(String[] args) throws InterruptedException {
//创建容器
Container container = new Container();
//创建入队列方法类,将容器类作为锁传入
AddService addService = new AddService(container);
//创建出队列方法类,将容器类作为锁传入
PopService getService = new PopService(container);
// 创建2个生产者线程
for (int i = 0; i < 2; i++) {
AddValueThread addValueThread = new AddValueThread(addService);
addValueThread.start();
}
Thread.sleep(8000);
// 创建3个消费者线程
for (int i = 0; i < 3; i++) {
PopValueThread popValueThread = new PopValueThread(getService);
popValueThread.start();
}
}
}
这个项目有三个要注意的点
1.AddService.class的notifyAll()
为什么要用notifyAll(),而不用notify(),因为notify()可能会通知同类,消费者通知消费者,
生产者通知生产者,这样它们就会一直等待
2. AddService.class的while (container.size() == 30)
while不能使用if替代,因为wait()在被唤醒之后程序会从wait()之后开始运行,要是此时容器大小条件
不满足就会溢出,需要再次判断
3.使用Container实例对象作为锁,那么 多生产者和多消费者本质上依然是排队生产,排队消费的,
所以可用使用this作为锁对象,但是使用this作为锁对象,那说明入队列服务和出队列服务锁对象不同,
那就算它们使用notify(),也无法通知彼此,具体看 我的一篇博文 ,所以必须使用一个定时方法,让它们各自唤醒各自,这也就造成了它们通信的假象,如在AddService.class添加一个方法
public class AddService {
private Container container;
public AddService(Container container) {
this.container = container;
}
public void addMethod() {
try {
synchronized (container) {
while (container.size() == 30) {
System.out.println("容器已满");
container.notifyAll();
container.wait();
}
}
Thread.sleep(500);
container.add();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void notifyService() {
try {
while (true) {
synchronized (this) {
if (box.size() < 30) {
this.notifyAll();
}
}
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
notifyService()方法先检测容器是否以及满了,再每隔一秒唤醒所有生产者线程
参考
《Java多线程编程核心技术》