同步实现:Java

同步实现:Java,java,multithreading,producer-consumer,thread-synchronization,Java,Multithreading,Producer Consumer,Thread Synchronization,这是一个消费者-生产者问题,我希望得到如下输出: Put:0 获取:0 Put:1 获取:1 …等等。 但与此相反,Consumer类多次使用相同的q值,尽管使用wait()和notify()方法。。以及生产者阶级超越消费者。如何获得同步输出? 这是QFixed类:(它定义put()和get()方法) 这是ProducerFixed类: class ProducerFixed implements Runnable{ Q q; Thread t; public vo

这是一个消费者-生产者问题,我希望得到如下输出:
Put:0
获取:0
Put:1
获取:1
…等等。
但与此相反,Consumer类多次使用相同的q值,尽管使用wait()和notify()方法。。以及生产者阶级超越消费者。如何获得同步输出?

这是QFixed类:(它定义put()和get()方法)

这是ProducerFixed类:

class ProducerFixed implements Runnable{
    Q q;
    Thread t;
    public volatile boolean flag = true;
        ProducerFixed(Q q){
            this.q = q;
            t = new Thread(this,"Producer");
            t.start();
        }

    @Override
        public void run(){
            int i =0 ;
            while(flag){
                q.put(i++);
            }
        }

    void stop() {
        flag = false;
    }
}
class ConsumerFixed implements Runnable{
    Q q;
    Thread t;
    public volatile boolean flag = true;

        ConsumerFixed(Q q){
            this.q = q;
            t = new Thread(this,"Consumer");
            t.start();
        }

    @Override
        public void run(){
            while(flag){
                q.get();
            }
        }

    public void stop() {
        flag = false;
    }
}
public class Producer_Consumer_Fixed {
    public static void main(String arg[]){
        Q q = new Q();
        Producer p = new Producer(q);
        Consumer c = new Consumer(q);

        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            System.out.println("interrupted");
        }

        p.stop();
        c.stop();
        try{
            p.t.join();
            c.t.join();
        }catch(InterruptedException e){
            System.out.println("interrupted");
        }
    }
}
这是ConsumerFixed类:

class ProducerFixed implements Runnable{
    Q q;
    Thread t;
    public volatile boolean flag = true;
        ProducerFixed(Q q){
            this.q = q;
            t = new Thread(this,"Producer");
            t.start();
        }

    @Override
        public void run(){
            int i =0 ;
            while(flag){
                q.put(i++);
            }
        }

    void stop() {
        flag = false;
    }
}
class ConsumerFixed implements Runnable{
    Q q;
    Thread t;
    public volatile boolean flag = true;

        ConsumerFixed(Q q){
            this.q = q;
            t = new Thread(this,"Consumer");
            t.start();
        }

    @Override
        public void run(){
            while(flag){
                q.get();
            }
        }

    public void stop() {
        flag = false;
    }
}
public class Producer_Consumer_Fixed {
    public static void main(String arg[]){
        Q q = new Q();
        Producer p = new Producer(q);
        Consumer c = new Consumer(q);

        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            System.out.println("interrupted");
        }

        p.stop();
        c.stop();
        try{
            p.t.join();
            c.t.join();
        }catch(InterruptedException e){
            System.out.println("interrupted");
        }
    }
}
这是生产者\消费者\固定类别:

class ProducerFixed implements Runnable{
    Q q;
    Thread t;
    public volatile boolean flag = true;
        ProducerFixed(Q q){
            this.q = q;
            t = new Thread(this,"Producer");
            t.start();
        }

    @Override
        public void run(){
            int i =0 ;
            while(flag){
                q.put(i++);
            }
        }

    void stop() {
        flag = false;
    }
}
class ConsumerFixed implements Runnable{
    Q q;
    Thread t;
    public volatile boolean flag = true;

        ConsumerFixed(Q q){
            this.q = q;
            t = new Thread(this,"Consumer");
            t.start();
        }

    @Override
        public void run(){
            while(flag){
                q.get();
            }
        }

    public void stop() {
        flag = false;
    }
}
public class Producer_Consumer_Fixed {
    public static void main(String arg[]){
        Q q = new Q();
        Producer p = new Producer(q);
        Consumer c = new Consumer(q);

        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            System.out.println("interrupted");
        }

        p.stop();
        c.stop();
        try{
            p.t.join();
            c.t.join();
        }catch(InterruptedException e){
            System.out.println("interrupted");
        }
    }
}

如果(flag)wait的QFixed get和put方法中使用的习惯用法被破坏,那么应该使用while循环。看

有一次,我更改了类的名称以删除“Fixed”,并将Q类中的
if
替换为
while
,如下所示:

class Q {
    int n;
    boolean valueset = false;

    synchronized int get(){
        while(!valueset){
            try {
                wait();
            } catch (InterruptedException ex) {
                System.out.println("interrupted");
            }
        }
        System.out.println("Got: " +n);
        valueset = false;
        notify();
        return n;
    }

    synchronized void put(int n){
        while (valueset){
            try {
                wait();
            } catch (InterruptedException ex) {
                System.out.println("interrupted");
            }
        }
        this.n = n;
        valueset = true;
        System.out.println("Put: "+n);
        notify();
    }
}
我从一开始就得到了输出

Put: 0
Got: 0
Put: 1
Got: 1
Put: 2
Got: 2
Put: 3
Got: 3
Put: 4
Got: 4
Put: 5
Got: 5
Put: 6
Got: 6
Put: 7
Got: 7
Put: 8
Got: 8
Put: 9
Got: 9
Put: 10
Got: 10
...
每个值放置和获取一次,这是您想要的输出

使用while循环是件好事,有几个原因

等待线程放弃监视器,一旦唤醒,它必须重新获取监视器,然后才能继续退出等待方法。这意味着其他线程可以使用监视器,并可能更改同步所保护的数据的状态。一旦线程重新获得监视器,它需要再次检查条件,然后才能知道它认为它收到通知的条件是否实际发生。否则,线程将根据过时的信息决定要做什么

在涉及三个或更多争用线程的示例中,这将是一个大问题。然而,对于这个特定的案例,我没有看到有问题的操作顺序

while循环的另一个原因是线程退出等待并不一定意味着发生了通知。根据报告:

线程也可以在不被通知、中断或超时的情况下唤醒,即所谓的虚假唤醒。虽然这种情况在实践中很少发生,但应用程序必须通过测试本应导致线程被唤醒的条件来防范这种情况,并在条件不满足时继续等待。换句话说,等待应该总是在循环中发生,如下所示:

synchronized(obj){
而()
对象等待(超时);
…//执行适合条件的操作
}

这来自JVM实现中的竞争条件;正如文件所说,这应该是罕见的。但这可能是问题的根源,在没有得到通知的情况下等待返回可能会产生与您所看到的类似的多个get的情况。

请修复代码中的编译错误,您的代码看起来很好。。如何修复编译错误??您向我们展示的代码不能是您正在执行的代码
new Q()
@JainamJhaveri-您已经编写了程序。。您所说的如何修复编译错误是什么意思?。你的类名错了。。纠正他们。。