0

Whether it's from a GUI or Console, how would either interact with Consumer? Should I simply expose consume as public, or perhaps package-private? That seems like it's stepping into a minefield.

Consumer:

package net.bounceme.dur.client;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.concurrent.BlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.bounceme.dur.data.State;
import net.bounceme.dur.data.Title;

public class Consumer implements Runnable {

    private final BlockingQueue<Title> queue;
    private ObjectOutputStream objectOutputStream = null;

    public Consumer(BlockingQueue<Title> queue, ObjectOutputStream objectOutputStream) {
        this.queue = queue;
        this.objectOutputStream = objectOutputStream;
    }

    private void consume() throws InterruptedException, IOException {
        Title title = queue.take();
        title.setState(State.x);
        objectOutputStream.writeObject(title);
    }

    @Override
    public void run() {
        try {
            consume();
        } catch (InterruptedException | IOException ex) {
            Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex);
            //exit?
        }
    }
}

the service:

package net.bounceme.dur.client;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Properties;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import net.bounceme.dur.data.Title;

public class ProducerConsumerService implements Executor {

    private static final Logger log = Logger.getLogger(ProducerConsumerService.class.getName());
    private final BlockingQueue<Title> queue = new ArrayBlockingQueue<>(1);
    private Producer producer = null;
    private Consumer consumer = null;

    public void ProducerConsumerService() {
    }

    public void produce() {
    }

    public void consume() {
    }

    public void startService() throws IOException {
        Properties props = PropertiesReader.getProps();
        int portNumber = Integer.parseInt(props.getProperty("port"));
        String host = props.getProperty("server");
        Socket socket = new Socket(host, portNumber);
        ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
        producer = new Producer(queue, objectInputStream);
        consumer = new Consumer(queue, objectOutputStream);
        new Thread((Runnable) producer).start();
        new Thread((Runnable) consumer).start();
        log.info("started...");
    }

    @Override
    public void execute(Runnable command) {
        new Thread(command).start();
    }
}

Or, alternately, do I add methods in the service to access the BlockingQueue? However, doing so seems to obviate the need for the Consumer class itself.

What's the correct usage of these three classes by an outside class, either a Console or Swing interface?

reference:

http://www.journaldev.com/1034/java-blockingqueue-example-implementing-producer-consumer-problem

Thufir
  • 8,216
  • 28
  • 125
  • 273
  • 1
    I usually connect the producer and consumer at construction time with a mediator...which might just be the BlockingQueue, or it might be something more substantial. As you scale up, a good design will allow you to also scale up producers and consumers independently. – David Ehrmann Jul 10 '14 at 16:32
  • so the Swing class can just `take` and `put` to the `BlockingQueue` directly from the service instance? – Thufir Jul 10 '14 at 16:47

1 Answers1

0

My concern with the following solution:

package net.bounceme.dur.client;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Properties;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import net.bounceme.dur.data.Title;

public class ProducerConsumerService implements Executor {

    private static final Logger log = Logger.getLogger(ProducerConsumerService.class.getName());
    private final BlockingQueue<Title> queue = new ArrayBlockingQueue<>(1);
    private Producer producer = null;
    private Consumer consumer = null;
    private Title title = null;

    public void ProducerConsumerService() {
    }

    public Title produce() throws InterruptedException, IOException, ClassNotFoundException {
        producer.produce();
        title = queue.take();
        consumer.consume(title);
        return title;
    }

    public void startService() throws IOException {
        Properties props = PropertiesReader.getProps();
        int portNumber = Integer.parseInt(props.getProperty("port"));
        String host = props.getProperty("server");
        Socket socket = new Socket(host, portNumber);
        ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
        producer = new Producer(queue, objectInputStream);
        consumer = new Consumer(queue, objectOutputStream);
        new Thread((Runnable) producer).start();
        new Thread((Runnable) consumer).start();
        log.info("started...");
    }

    @Override
    public void execute(Runnable command) {
        new Thread(command).start();
    }
}

is that it breaks encapsulation by exposing too much of Produceer and Consumer through the produce() method in the service.

Thufir
  • 8,216
  • 28
  • 125
  • 273