本程序如何修改才能达到下面的效果:
生产的新数据是:1
读到的数据是:1
生产的新数据是:2
读到的数据是:2
生产的新数据是:3
读到的数据是:3
生产的新数据是:4
读到的数据是:4源文件:
package 多线程;
//生产者与消费者的同步问题 。生产者放入一个整数到共享区中,仅当消费者取走后才能继续放入
class  HoldInt{
private int sharedInt; //共享区只能存入一个数
private  boolean writeAble = true;//表示生产者能生产新数据
public synchronized void set(int val){  //对临界区的写操作
while(!writeAble){ //进入等待
try{
wait();
}catch(InterruptedException e){}
}
    sharedInt = val;
writeAble = false; //表示生产者不能放入数据
notify();//唤醒消费者
}

public synchronized int get(){ //对临界区的读操作
while(writeAble){
try{
wait();
}catch(InterruptedException e){}
}
writeAble = true;
notify();//唤醒生产者
return sharedInt;
}
}
//生产者线程
class ProduceInt extends Thread{
private HoldInt hi;
public ProduceInt(HoldInt hiForm){
hi = hiForm;
}

public void run(){
for(int i=1;i<=4;i++){
hi.set(i);
System.out.println("生产的新数据是:"+i);
}
}
}
//消费者线程
class ConsumeInt extends Thread{
private HoldInt hi;
public ConsumeInt(HoldInt hiForm){
hi = hiForm;
}
public void run(){
for(int i=1;i<=4;i++){
int val = hi.get();
System.out.println("读到的数据是:"+val);
}
}
}public class Productor_Consumer {
public static void main(String[] args){
HoldInt h = new HoldInt();//h为监控器
ProduceInt p = new ProduceInt(h);
ConsumeInt c = new ConsumeInt(h);
p.start();
c.start();
}
}

解决方案 »

  1.   

    public class ProduceConsume {
    public static void main(String[] args) {
    SyncStack ss = new SyncStack();
    Producer p = new Producer(ss);
    Consumer c = new Consumer(ss);
    new Thread(p).start();//一个生产者
    new Thread(c).start();//一个消费者
    }
    }class WoTou {
    int id; 
    WoTou(int id) {
    this.id = id;
    }
    public String toString() {
    return "WoTou : " + id;
    }
    }class SyncStack {         //存放生产品的类
    int index = 0;
    WoTou[] arrWT = new WoTou[6];

    public synchronized void push(WoTou wt) {
    while(index == arrWT.length) {
    try {
    this.wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    this.notifyAll();
    arrWT[index] = wt;
    index ++;
    }

    public synchronized WoTou pop() {
    while(index == 0) {
    try {
    this.wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    this.notifyAll();
    index--;
    return arrWT[index];
    }
    }class Producer implements Runnable {      //生产者的类
    SyncStack ss = null;
    Producer(SyncStack ss) {
    this.ss = ss;
    }

    public void run() {
    for(int i=0; i<20; i++) {
    WoTou wt = new WoTou(i);
    ss.push(wt);
    System.out.println("生产了:" + wt);
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
    }class Consumer implements Runnable {          //消费者的类
    SyncStack ss = null;
    Consumer(SyncStack ss) {
    this.ss = ss;
    }

    public void run() {
    for(int i=0; i<60; i++) {
    WoTou wt = ss.pop();
    System.out.println("消费了: " + wt);
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
    }
      

  2.   

    个人觉得:
    把System.out.println("生产的新数据是:")放入同步逻辑中的sharedInt = val后,另一个打印也已一样
      

  3.   

    恩不错  当初学操作系统的时候写的都是伪代码  还没用JAVA写过啊!不错 顶
      

  4.   

    lz已经同步了 像3楼所说,你的打印位置放得不对,试改成了下面这样
    public class HoldInt { private int sharedInt; // 共享区只能存入一个数
    private boolean writeAble = true;// 表示生产者能生产新数据 public synchronized void set(int val) { // 对临界区的写操作
    while (!writeAble) { // 进入等待
    try {
    wait();
    } catch (InterruptedException e) {
    }
    }
    sharedInt = val;
    writeAble = false; // 表示生产者不能放入数据
    System.out.println("生产的新数据是"+ val);
    notify();// 唤醒消费者
    } public synchronized int get() { // 对临界区的读操作
    while (writeAble) {
    try {
    wait();
    } catch (InterruptedException e) {
    }
    }
    writeAble = true;
    notify();// 唤醒生产者
    int ret = sharedInt;
    System.out.println("读到的数据是"+ ret);
    return ret;
    }}
      

  5.   

    看着    * py330316117用户头像
        * py330316117
        * (py330316117)
        *
        * 等 级:
        *就郁闷   
      

  6.   

    我不知道为会么非要这么实现,我们公司以前搞的一个ORACLE AQ就是这种原理,一个进就得一个出,否则就得等待,非常的不好用,有一种改良的办法看能不能达到你的要求
    方法跟上面的两段代码类似,是我实现过的,至今还觉得用的效果不错,建一个公共堆盏,一个线程管进一个线程管出,进的时候不能出,出的时候不能进,先进后出,后进先出,一次执行一个,交叉执行就能达到你的效果,他还有一个好处,如果不做交叉,可以大大的提高性能。
    也可以搞一个队列,一边进一边出,测试时显示顺序可能不一样,但是在执行业务逻辑的时候,决对错不了。
      

  7.   

    //生产者与消费者的同步问题 。生产者放入一个整数到共享区中,仅当消费者取走后才能继续放入 
    class  HoldInt{ 
    private int sharedInt; //共享区只能存入一个数 
    private  boolean writeAble = true;//表示生产者能生产新数据 
    public synchronized void set(int val){  //对临界区的写操作 
    while(!writeAble){ //进入等待 
    try{ 
    wait(); 
    }catch(InterruptedException e){} 

    sharedInt = val; 
    System.out.println("生产的新数据是:"+sharedInt); 
    writeAble = false; //表示生产者不能放入数据 
    notify();//唤醒消费者 
    } public synchronized void get(){ //对临界区的读操作 
    while(writeAble){ 
    try{ 
    wait(); 
    }catch(InterruptedException e){} 

    System.out.println("消费储的新数据是:"+sharedInt);
    writeAble = true;
    notify();//唤醒生产者 


    //生产者线程 
    class ProduceInt extends Thread{ 
    private HoldInt hi; 
    public ProduceInt(HoldInt hiForm){ 
    hi = hiForm; 
    } public void run(){ 
    for(int i=1;i <=4;i++){ 
    hi.set(i); 



    //消费者线程 
    class ConsumeInt extends Thread{ 
    private HoldInt hi; 
    public ConsumeInt(HoldInt hiForm){ 
    hi = hiForm; 

    public void run(){ 
    for(int i=1;i <=4;i++){ 
    hi.get(); 


    } public class Productor_Consumer { 
    public static void main(String[] args){ 
    HoldInt h = new HoldInt();//h为监控器 
    ProduceInt p = new ProduceInt(h); 
    ConsumeInt c = new ConsumeInt(h); 
    p.start(); 
    c.start(); 

    } 程序的打印出现了问题,没有对打印的顺序进行同步
      

  8.   

    大家说是不是java设计的好就是一synchronized 加Object的wait notify 就可以实现线程同步 互斥
      

  9.   

    而不用 mutex 和 semphore(好像是这样写)
      

  10.   

    回复37楼
     你写的程序没问题啊 !怎么没有对打印的顺序进行同步啊,不是已经synchronized了吗