• Post Reply Bookmark Topic Watch Topic
  • New Topic

Producer Consumer (3 threads)

 
Taylor Callihan
Greenhorn
Posts: 5
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have this code, it reads an image, processes it and applies a filter, then writes that filtered image back in the same directory as the original:



I NEED to turn these into 3 threads: a file reader, a image processor, and a file writer.
The file reader thread is a producer of input images that it reads and loads in main memory (vector or queue?). The image processor thread is a consumer of input images and a producer of filtered images. The image writer is a consumer of filtered images that it writes from main memory to disk.
When a thread attempts to read from an empty buffer, the thread must sleep to be awakened later when the buffer's no longer empty. When a thread attempts to write to a full buffer, the thread must sleep to be awakened when the buffer's no longer full.

Can i please have some insight or examples on how to do this? Not much helpful sources online. thanks in advance.
 
Paul Clapham
Sheriff
Posts: 21892
36
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here's a reasonably good tutorial about how to use a BlockingQueue to implement an asynchronous producer/consumer pair: http://tutorials.jenkov.com/java-util-concurrent/blockingqueue.html

You'll need two queues, one to send the original images to the image processor and the other to send the filtered images to the image writer.

Don't even think of trying to use low-level threading primitives like Thread.wait() unless it's a non-negotiable requirement for this problem.
 
Paul Clapham
Sheriff
Posts: 21892
36
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And welcome to the Ranch!
 
gyank kannur
Ranch Hand
Posts: 43
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I believe you need only two threads. I tried implementing a BlockingQueue but looks like the consumer is running before the producer and hence the new images are not being created.


public class ThreadedImageProcessor {

public static void main(String[] args) {

BlockingQueue<Image> queue = new ArrayBlockingQueue<Image>(2);

Producer producer = new Producer(queue);
Consumer consumer = new Consumer(queue);

new Thread(producer).start();
try {
Thread.sleep(3000); //Need a lag otherwise consumer thread completes before producer actually puts anything to queue
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new Thread(consumer).start();
}
}

class Producer implements Runnable {

private String directory = "c:\\files";
private String fileName = ("even");
BufferedImage input = null;
BufferedImage output;

protected BlockingQueue<Image> queue = null;

public Producer(BlockingQueue<Image> queue) {
this.queue = queue;
}

public void run() {

File currentDir = new File(directory);
File[] contents = currentDir.listFiles();

for (int i = 0; i < contents.length; i++) {
String image = directory + contents[i].getName();

try {
input = ImageIO.read(new File(image)); // READ
System.out.print("r");

} catch (IOException e) {
System.out.println("Cant read file");
System.exit(1);
}

if (input != null)
output = new BufferedImage(input.getWidth(), input.getHeight(), input.getType());

if (fileName.equalsIgnoreCase("even"))
{
String smear = directory +"smear_" + contents[i].getName();
// consumeImage(output, smear); // WRITE
Image im= new Image();
im.setImage(output);
im.setFile(smear);
try {
queue.put(im);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print("w");

}

else {
String oil1 = directory+ "oil1_" + contents[i].getName();
// consumeImage(output, oil1); // WRITE
Image im= new Image();
im.setImage(output);
im.setFile(oil1);
try {
queue.put(im);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print("w");
}
} // for

}
}

class Consumer implements Runnable{

protected BlockingQueue<Image> queue = null;

public Consumer(BlockingQueue<Image> queue) {
this.queue = queue;
}

public void run() {
try {

while (!queue.isEmpty()) {

Image imageBean =new Image();
imageBean = queue.take();
try {
ImageIO.write(imageBean.getImage(), "jpg", new File(imageBean.getFile()));
} catch (IOException e) {
System.out.println("Cannot write file "+imageBean.getFile());
System.exit(1);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

 
gyank kannur
Ranch Hand
Posts: 43
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I believe you need only two threads. I tried implementing a BlockingQueue but looks like the consumer is running before the producer and hence the new images are not being created. Am I missing something??

 
Henry Wong
author
Sheriff
Posts: 22542
109
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
gyank kannur wrote:I believe you need only two threads. I tried implementing a BlockingQueue but looks like the consumer is running before the producer and hence the new images are not being created. Am I missing something??


The main purpose of a blocking queue is that ... it blocks !!

When there is nothing for the consumer, it is supposed to wait for the elements. You are not allowing the queue to do that. The way you coded it, you will exit as soon as the queue is empty. This is true if the consumer runs before the producer -- but it is also true if the consumer get ahead of the producer.

Henry
 
gyank kannur
Ranch Hand
Posts: 43
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oh I got it!! Thank you.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!