Java并发与多线程(2) 生产者与消费者
来源:互联网 发布:京东和淘宝哪个靠谱 编辑:程序博客网 时间:2024/05/19 13:06
老师的源码
public class Producer extends Thread { private Tray tray; private int id; public Producer(Tray t, int id) { tray = t; this.id = id; } public void run() { for (int i = 0; i < 10; i++) for(int j =0; j < 10; j++ ) { tray.put(i, j); System.out.println("Producer #" + this.id + " put: ("+i +","+j + ")."); try { sleep((int)(Math.random() * 100)); } catch (InterruptedException e) { } }; } }public class Consumer extends Thread { private Tray tray; private int id; public Consumer(Tray t, int id) { tray = t; this.id = id; } public void run() { int value = 0; for (int i = 0; i < 10; i++) { value = tray.get(); System.out.println("Consumer #" + this.id + " got: " + value); } } }public class Tray { private int x,y; private boolean available = false; public synchronized int get() { while (available == false) { try { wait(); } catch (InterruptedException e) { } } available = false; // 此时available为真,确保所有其他消费者等待 notifyAll(); return x+y; } public synchronized void put(int a, int b) { while (available == true) { try { wait(); } catch (InterruptedException e) { } } available = true; // 唤醒等待队列中的其他消费者或生产者 x= a; y = b; notifyAll(); }}public class ProducerConsumerTest { public static void main(String[] args) { Tray t = new Tray(); Producer p1 = new Producer(t, 1); Consumer c1 = new Consumer(t, 1); p1.start(); c1.start(); } }
今天看了一下老师给的代码,跑了一下发现会有bug:即生产者的产品输出会在消费者的购买的输入之后(部分),尝试了几种改的方法
我最终的改法
import java.lang.Thread; class Producer extends Thread {private Tray tray;private int id;public Producer ( Tray t, int id){tray = t;this.id = id;//new Thread(this,"Producer");}public void run () {for( int i = 0; i < 10; i++) {for( int j = 0; j < 10; j++) {synchronized(tray){tray.put(i, j);System.out.println("Producer #" + id + "put:(" + i + "," + j + ").");}try{ sleep(100); // 这个sleep可以去掉的,不影响} catch( InterruptedException e ) {System.out.println("Producer Interrupted");}}//System.out.println("hhhh");}}}class Consumer extends Thread {private Tray tray;private int id;public Consumer ( Tray t, int id ) {tray = t;this.id = id;//new Thread(this,"Consumer");}public void run () {int value = 0;for( int i = 0; i < 100; i++) {synchronized (tray) {value = tray.get();System.out.println("Consumer #" + id + "got: " + value);//try{//sleep(10);//} catch ( InterruptedException e ) {//System.out.println("Consumer Interrupted");}}}}class Tray {private int x;private int y;private boolean available = false;public synchronized int get() {while ( available == false ) {try{wait();} catch( InterruptedException e ) {System.out.println("Tray Wrong");}}//System.out.println("Consumer #" + "got: " + (x+y));available = false;super.notify();return x + y;//notifyAll();}public synchronized void put( int a, int b) {while ( available == true ) {try{wait();} catch( InterruptedException e) {System.out.println("Tray Wrong 2");}}//System.out.println("Producer #" + "put:(" + a + "," + b + ").");available = true;x = a;y = b;super.notify();//notifyAll();}}public class Test {public static void main ( String [] args ) {Tray t = new Tray();Producer p1 = new Producer(t,1);Consumer c1 = new Consumer(t,1);p1.start();c1.start();try{Thread.sleep(10000);} catch ( InterruptedException e ) {System.out.println("Thread Interrupted");}System.out.println("End");}}
做的改动有
1.改变了消费者类的run()方法的循环次数,改成了100次,和生产者的总循环次数保持一致
2.把run()方法里面的进行put()或者get()和输出用synchronized块括起来
分析:
出现bug的原因不是先消费后生产,而是因为print的时候会有延迟,这个延迟多久也是不好控制的,然后这个时候消费者已经可以开始消费了,就导致了消费者的输出先于生产者,所以写同步块的效果就是把输出的时候限定在切换到另一个进程之前。这样子的话,把put和get方法的前面的synchronized关键字去掉也是可以的。
0 0
- Java并发与多线程(2) 生产者与消费者
- Java多线程与并发(五)之生产者与消费者案例
- java多线程 生产者与消费者
- 【Java多线程】-生产者与消费者
- JAVA - 多线程 - 生产者与消费者
- Java多线程-生产者与消费者
- 多线程---生产者与消费者
- 多线程(生产者与消费者)
- 多线程 生产者与消费者
- 经典多线程Java实例 生产者与消费者
- JAVA多线程实例(生产者与消费者问题)
- JAVA 多线程之生产者与消费者
- Java多线程之生产者与消费者
- java多线程同步:生产者与消费者问题
- Java多线程--生产者与消费者问题
- Java多线程之生产者与消费者
- Java经典多线程问题--生产者与消费者
- Java多线程之 生产者与消费者
- Android WIFI模块分析
- linux中gets()函数和fgets()函数
- 函数参数的传递问题(一级指针和二级指针)
- 为什么要使用copy_from_user?
- linux设备驱动归纳总结(三):4.ioctl的实现
- Java并发与多线程(2) 生产者与消费者
- arm中的PLL,MPLL,UPLL,FCLK,HCLK,PCLK的作用概述
- NOR FLASH驱动程序
- 存储管理
- Linux驱动学习笔记(3)字符设备驱动
- Linux 错误码列表
- linux设备驱动归纳总结(五):2.操作硬件——IO内存
- 不要对知识与技术的遗忘感到焦虑
- linux设备驱动归纳总结(四):5.SMP下的竞态和并发