一.模型定义
1.生产者持续生产,直到缓冲区满,阻塞;2.缓冲区不满后,继续生产消费者持续消费,直到缓冲区空,阻塞;3.缓冲区不空后,继续消费生产者可以有多个,消费者也可以有多个
二.几种写法
1.常规写法:
/**
* @author Seven 消费者线程 可能有多个消费者
*
*/
public class Consumer extends Thread{
Repo repo;
public Consumer(Repo repo) {
super();
this.repo = repo;
}
@Override
public void run() {
super.run();
while(true) {
repo.remove();
try {
Thread.sleep(5000); //凸显生产线程超过额定数量时阻塞
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/**
* @author Seven 生产者线程
*
*/
public class Producer extends Thread{
Repo repo;
public Producer(Repo repo) {
super();
this.repo = repo;
}
@Override
public void run() {
super.run();
while(true) {
repo.add();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/**
* @author Seven 仓库类
*
*/
public class Repo {
int capacity = 10; // 仓库最大容量
List<Integer> repsList = new ArrayList<Integer>(); // 共享数据区
/**
* 同步方法,向共享数据区添加数据,如果当前数据区等于仓库最大容量, 需要让生产线程等待执行
*
*/
public synchronized void add() {
String name = Thread.currentThread().getName();
if (repsList.size() == 10) {
// 最大容量,等待
try {
System.out.println(name + "添加货物失败" + ",已经超过仓库最大容量了,线程阻塞中,需要等待添加。。。。。");
wait();
System.out.println("线程等待后执行》》》》》》》》》》》");
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
repsList.add(1);
System.out.println(name + "添加货物成功");
System.out.println("只要有货物,生产者就唤醒消费线程获取货物《《《");
notifyAll();// 唤醒在此对象监视器上等待的线程
}
}
/**
* 同步方法,移除共享数据区第一条数据,如果没有数据,则让其线程等待
*/
public synchronized void remove() {
String name = Thread.currentThread().getName();
if (repsList.size() == 0) {
try {
notifyAll();
System.out.println(name + "消费货物失败" + ",仓库已经没有货物了,需要生产者生产货物。。。");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
repsList.remove(0);
System.out.println(name + "消费货物成功");
}
}
}
package com.ts.consumer;
/**
* @author Seven 测试类
*
*/
public class TsMain {
public static void main(String[] args) {
Repo repo=new Repo();
Producer p=new Producer(repo);
p.setName("生产者线程");
Consumer c1=new Consumer(repo);
Consumer c2=new Consumer(repo);
c1.setName("小明消费者");
p.start();
c1.start();
}
}
输出日志:
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
小明消费者消费货物成功
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
生产者线程添加货物失败,已经超过仓库最大容量了,线程阻塞中,需要等待添加。。。。。
2.用阻塞队列实现
生产者:
public class Producer extends Thread{
public Producer(BlockingQueue bq) {
super();
this.bq = bq;
}
BlockingQueue bq;
@Override
public void run() {
super.run();
while(true) {
try {
System.out.println("生产数据");
bq.put(1);//put()方法:类似于我们上面的生产者线程,容量达到最大时,自动阻塞。
Thread.sleep(300);
} catch (InterruptedException e) {
System.out.println("生产数据异常");
e.printStackTrace();
}
}
}
}
消费者:
public class Consumer extends Thread{
BlockingQueue bq;
public Consumer(BlockingQueue bq) {
super();
this.bq = bq;
}
@Override
public void run() {
super.run();
while(true) {
try {
System.out.println(getName()+"取出"+bq.take());//take()方法:类似于我们上面的消费者线程,容量为0时,自动阻塞。
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
System.out.println("取出异常");
e.printStackTrace();
}
}
}
}
测试代码
public class TsMain {
public static void main(String[] args) {
BlockingQueue bq=new LinkedBlockingQueue(10);
Consumer c=new Consumer(bq);
c.setName("c1");
Producer p=new Producer(bq);
Consumer c2=new Consumer(bq);
c2.setName("c2");
c.start();
p.start();
c2.start();
}
}
测试打印
生产数据
c1取出1
生产数据
c2取出1
生产数据
生产数据
c1取出1
生产数据
c2取出1
生产数据
生产数据
c1取出1
生产数据
c2取出1
生产数据
生产数据
c1取出1
生产数据
c2取出1
生产数据
生产数据
生产数据
c1取出1
生产数据
c2取出1
生产数据
生产数据
341



被折叠的 条评论
为什么被折叠?



