对如何在java中使用交换器感到困惑

时间:2015-01-07 16:22:19

标签: java

与基本上每个交换器任务一样,我有一个生产者填充空缓冲区2,消费者清空完整缓冲区1,当每个线程完成时,它们应该交换它们各自的缓冲区。

我真的不确定应用交换的地点和方式。我将readyconsumer和readyproducer定义为布尔值,这样第三个线程可以检查是否有时间在两者都为真时交换缓冲区。这应该解决我用两个线程做的问题,其中程序在wait()处遇到了两个线程(遗憾的是它仍然存在)。

这就是目前代码的样子。任何人都可以帮助我在哪个课程中交换以及在代码中的哪一点?非常感谢你提前!

    class Buffer {
        static boolean readyconsumer, readyproducer = false;

        volatile int count; // number of put actions
        static int max = 10;

        Buffer() {
        count = 0;
        }

        public synchronized void put() {
            if (count == max) {
                readyproducer = true;
                System.out.println("          wait ");
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
            count++;
            System.out.println("put " + count);
            notifyAll();
        }

        public synchronized void get() {
            if (count == 0) {
                readyconsumer = true;
                System.out.println("          wait");
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
            count--;
            System.out.println("get " + count);
            notifyAll();
        }
    }


class CheckandSwitch extends ProdCon {
    public void run() {

        while (true) {

            if (Buffer.readyconsumer && Buffer.readyproducer) {
                try {
                    ProdCon.buffer2 = exchanger.exchange(ProdCon.buffer1);
                    ProdCon.buffer1 = exchanger.exchange(ProdCon.buffer2);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    }
                Buffer.readyconsumer = false;
                Buffer.readyproducer = false;
                buffer1.count = 0;
                buffer2.count = 10;
                notifyAll();
            }

        }
    }

}

class Consumer extends ProdCon {
    static Buffer buffer;

    Consumer(Buffer b) {
        super();
        buffer = b;
        b.count = 10;
    }

    public void run() {
        while (true) {
            consume();
            buffer.get();
        }
    }

    private void consume() {
        System.out.println("consume");
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
        }
    }
}

class Producer extends ProdCon {
    static Buffer buffer;

    Producer(Buffer b) {
        super();
        buffer = b;
        b.count = 0;
    }

    public void run() {
        while (true) {
            produce();
            buffer.put();
        }
    }

    private void produce() {
        System.out.println("produce ");
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
        }
    }
}

import java.util.concurrent.*;

public class ProdCon extends Thread {
    static Exchanger<Buffer> exchanger = new Exchanger<Buffer>();
    static Buffer buffer1, buffer2 = null;

    public static void main(String[] args) {

        buffer1 = new Buffer();
        buffer2 = new Buffer();
        new Consumer(buffer1).start();
        new Producer(buffer2).start();
        new CheckandSwitch().start();

    }
}

1 个答案:

答案 0 :(得分:1)

您可以使用Exchanger

这是来自javadoc的代码调整为一个工作示例。

class DataBuffer<T> {

    T data = null;

    public boolean isFull() {
        return data != null;
    }

    public boolean isEmpty() {
        return data == null;
    }

    public T get() {
        T d = data;
        data = null;
        return d;
    }

    public void put(T data) {
        this.data = data;
    }
}

class FillAndEmpty {

    Exchanger<DataBuffer<Integer>> exchanger = new Exchanger<>();
    DataBuffer<Integer> initialEmptyBuffer = new DataBuffer<>();
    DataBuffer<Integer> initialFullBuffer = new DataBuffer<>();
    int countDown = 10;

    class FillingLoop implements Runnable {

        @Override
        public void run() {
            DataBuffer currentBuffer = initialEmptyBuffer;
            try {
                while (currentBuffer != null && countDown > 0) {
                    addToBuffer(currentBuffer);
                    if (currentBuffer.isFull()) {
                        currentBuffer = exchanger.exchange(currentBuffer);
                    }
                }
            } catch (InterruptedException ex) {
            }
        }

        private void addToBuffer(DataBuffer<Integer> currentBuffer) {
            currentBuffer.put(countDown--);
        }
    }

    class EmptyingLoop implements Runnable {

        @Override
        public void run() {
            DataBuffer<Integer> currentBuffer = initialFullBuffer;
            try {
                while (currentBuffer != null) {
                    takeFromBuffer(currentBuffer);
                    if (currentBuffer.isEmpty()) {
                        currentBuffer = exchanger.exchange(currentBuffer);
                    }
                }
            } catch (InterruptedException ex) {
            }
        }

        private void takeFromBuffer(DataBuffer<Integer> currentBuffer) {
            System.out.println(currentBuffer.get());
        }
    }

    void start() {
        new Thread(new FillingLoop()).start();
        new Thread(new EmptyingLoop()).start();
    }
}

public void test() {
    System.out.println("Hello");
    new FillAndEmpty().start();
}