Reputation: 10618
I am trying to write a mail utility that places mails in a queue, and it is later consumed by a consumer thread.
I am trying to implement a typical producer-consumer pattern, but something is going wrong.
I just wrote a skeleton , and the skeleton is not working as expected.
MailProducer.java
public class MailProducer implements Callable<Void>
{
@Override
public Void call() throws Exception
{
System.out.println("inside mail Producer");
System.out.println("Thread executing = " +
Thread.currentThread().getName());
return null;
}
}
MailConsumer.java
public class MailConsumer implements Callable<Void>
{
@Override
public Void call() throws Exception
{
System.out.println("inside mail consumer");
System.out.println("Thread executing = " +
Thread.currentThread().getName());
return null;
}
}
and finally the Executor
MailExecutor.java
public class MailExecutor
{
private static final int NTHREADS = 25;
private static final ExecutorService exec =
Executors.newFixedThreadPool(NTHREADS);
public static void main(String[] args)
{
exec.submit(new MailConsumer());
exec.submit(new MailProducer());
System.out.println("inside main");
}
}
Now when I run the program, I expect it to go back and forth the producer and consumer to keep printing what is written in the respective classes. But instead , the program hangs/does nothing after printing the below lines . What is going wrong ? Am I missing something?
Output ...(Output is not what I had expected. What is going wrong ?)
inside mail consumer
inside main
Thread executing = pool-1-thread-1
inside mail Producer
Thread executing = pool-1-thread-2
Upvotes: 3
Views: 2945
Reputation: 425448
You are missing the shared queue. Without the queue, you have nothing.
Producers put work onto the queue. Consumers take work off the queue. Use a BlockingQueue
, whose put()
and take()
methods are blocking calls. Running producers and consumers in separate threads allows them to safely block while calling these methods.
Neither the producers nor the consumers need to be Callable
; Runnable
will do. Using an Executor
to tie it all together is a good idea.
Upvotes: 2
Reputation: 3260
You must use loops so that your producer/consumer code is executed more than once.
Your threads do not communicate with each other. Currently you have only two threads being executed. Look at the example in the BlockingQueue javadoc of how to do it.
Upvotes: 0
Reputation: 10239
ExecutorService.submit schedules a Runnable or Callable for one execution. Your output shows that MailProducer and MailConsumer both executed once, so everything works like it should.
You should place the inside of your Producer and Consumer methods in loops:
import java.util.concurrent.*;
public class Executor {
private static final int NTHREADS = 25;
private static final ExecutorService exec =
Executors.newFixedThreadPool(NTHREADS);
public static void main(String[] args) {
exec.submit(new MailConsumer());
exec.submit(new MailProducer());
System.out.println("inside main");
}
static class MailProducer implements Runnable {
@Override
public void run() {
while (true) {
System.out.println("inside mail Producer");
System.out.println("Thread executing = " +
Thread.currentThread().getName());
}
}
}
static class MailConsumer implements Runnable {
@Override
public void run() {
while (true) {
System.out.println("inside mail Consumer");
System.out.println("Thread executing = " +
Thread.currentThread().getName());
}
}
}
}
This gives the output you expect.
Upvotes: 1