写在前面:各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢!
实现生产者消费者模型
1.创建生产者类
public class Producer implements Runnable{
private List<Integer> container;
public Producer(List<Integer> container){
this.container = container;
}
@Override
public void run() {
try {
while (true){
produce();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void produce() throws InterruptedException{
synchronized (container) {
while(container.size() == 5){
System.out.println("11111111111111111111");
container.wait();
}
Integer p = new Random().nextInt(10);
Thread.sleep(1000);
container.add(p);
System.out.println("生产产品:" + p);
container.notifyAll();
}
}
}
新建一个生产者类,container模拟容器大小,当container长度为5时就停止生产进入等待状态,并且会打印111111111这段话,当容器不满的时候会持续生产,生产的同时消费者也同时消费容器中的数据。
2.创建消费者类
public class Consumer implements Runnable{
private List<Integer> container;
public Consumer(List<Integer> container){
this.container = container;
}
@Override
public void run() {
try {
while (true){
consume();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void consume() throws InterruptedException{
synchronized (container){
while (container.isEmpty()){
System.out.println("2222222222222222222");
container.wait();
}
Thread.sleep(1000);
Integer product = container.remove(0);
System.out.println("消费产品:" + product);
container.notifyAll();
}
}
}
消费者类跟生产者差不多,container模拟容器大小,当container中的数据都消费完为空时就停止消费进入等待状态,并且会打印2222这段话,当容器不为空的时候会持续消费,消费的同时生产者也同时生产。
3.创建测试类测试
public static void main(String[] args) {
List<Integer> container = new ArrayList<>();
Thread producer = new Thread(new Producer(container));
producer.start();
Thread consumer = new Thread(new Consumer(container));
consumer.start();
}
初始化一个容器给生产者用来存储生产的产品,消费者消费也是从这个容器中消费,启动后控制台打印如下:
为了更好的测试效果,可以启动多个生产者线程。
看网上介绍wait notify的时候除了用来实现生产者消费者模型,还提到过交替打印,也就是两个线程交替执行,
其实生产者消费者模型跟交替打印是一样的,也是生产者和消费者线程交替的执行的一种,只不过因为有容器容量的限制,不能达到真正的两个线程交替执行的效果。
上篇中已经介绍了wait()、notify()、notifyAll()是对象的方法,再补充一下,既然wait交出的是对象的控制权,notify唤醒的是等待这个对象控制权的线程,那么在使用的时候wait和notify需要注意多个线程抢夺和释放的是同一对象的控制权,synchronized锁的是同一对象。
补充一下交替打印的代码:
public static void main(String[] args) {
List list1 = Arrays.asList(1,3,5,7,9);
List list2 = Arrays.asList(2,4,6,8,10);
Object obj = new Object();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < list1.size(); i++) {
synchronized (obj){
System.out.println(list1.get(i));
obj.notify();
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < list2.size(); j++) {
synchronized (obj){
System.out.println(list2.get(j));
obj.notify();
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
}
如上:两个线程分别遍历两个集合,实现交替打印,最终打印的结果为 1,2,3.。。9.10;注意这个obj就是让两个线程操作的是同一个对象,有的地方把obj叫做是synchronized的监视器。