Producer consumer using blockingqueue - java

I have started learning threads and tried Producer consumer problem in Java using concurrent package introduced in JDK 5.0 I have written the following code:
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
class Producer implements Runnable {
private final BlockingQueue<Integer> objqueue;
Producer(BlockingQueue<Integer> obj) {
objqueue = obj;
}
#Override
public void run() {
int i = 0;
while (i < 10) {
try {
System.out.println("Put : " + i);
objqueue.put(i);
} catch (InterruptedException e) {
}
i++;
}
}
}
class Consumer implements Runnable {
private final BlockingQueue<Integer> objqueue;
Consumer(BlockingQueue<Integer> obj) {
objqueue = obj;
}
#Override
public void run() {
while (true) {
try {
System.out.println("Got : " + objqueue.take());
} catch (InterruptedException e) {
}
}
}
}
public class PCMain {
public static void main(String[] args) {
// create shared object
BlockingQueue<Integer> obj = new LinkedBlockingQueue<Integer>();
Thread prod = new Thread(new Producer(obj));
Thread cons = new Thread(new Consumer(obj));
prod.start();
cons.start();
}
}
The program is not terminating when the producer has produced up to 9 and consumer consumed up to 9. Should I remove the while loop which is true forever in Consumer.
How can I make it for more than one Producer and one Consumer?
Thanks.

Well you have two threads, one should stop once i == 10. The other thread is in an infinite loop though. You need to signal to the consuming thread that the application should end. Look at the Poison Pill as a way of telling the second thread to stop.
The program itself won't stop until that consuming thread completed.

Removing while loop will cause consumer will consume only 1 object given by producer.
Better to go Excecuter framework. It is having Thread Factory and Thread Pool.You can use to implement the same.

I think the easiest way to "fix" your code is to make the consumer a daemon thread.
Thread prod = new Thread(new Producer(obj));
Thread cons = new Thread(new Consumer(obj));
cons.setDaemon( true );
prod.start();
cons.start();
This really isn't a general solution, but a good trick to keep in mind when it's inconvenient to signal a thread to stop.

Related

How to maintain order of execution of consumer threads

I am running code for one producer and multiple consumers. I want to prioritize execution of consumer threads. i.e. if I have consThread1, consThread2, consThread3. my question is how to restrict consThread3 to consume before consThread1 and consThread2
Producer.java
import java.util.concurrent.BlockingQueue;
import org.json.simple.JSONObject;
public class Producer implements Runnable {
private final BlockingQueue<Message> sharedQueue;
#SuppressWarnings("unchecked")
public Producer(BlockingQueue<Message> sharedQueue){
this.sharedQueue=sharedQueue;
}
#Override
public void run() {
try{
for(int i=0;i<4;i++) {
Message msg=new Message(""+i);
System.out.println("Producer Produced: " +msg.getMessage());
sharedQueue.put(msg);
Thread.sleep(400);
}
sharedQueue.put(new Message("exit")); // end of producing
System.out.println("-------Producer STOPPED------");
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Consumer.java
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import org.json.simple.JSONObject;
public class Consumer implements Runnable{
private final BlockingQueue<Message> sharedQueue;
private String threadId;
public Consumer(BlockingQueue<Message> sharedQueue) {
this.sharedQueue=sharedQueue;
}
#SuppressWarnings("unchecked")
#Override
public void run() {
threadId = "Consumer-" + Thread.currentThread().getName();
try {
Message msg;
while (true){
msg=sharedQueue.poll(5,TimeUnit.SECONDS);
if(msg.getMessage()=="exit" || msg.getMessage()==null){
sharedQueue.put(new Message("exit"));
break;
}
System.out.println(threadId + ": Consuming Message " + msg.getMessage());
Thread.sleep(1000);
}
System.out.println(threadId + " STOPPED Consuming ");
}
catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
Test program ProducerConsumer.java
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.json.simple.JSONObject;
public class ProducerConsumer {
public static void main(String[] args) throws InterruptedException {
BlockingQueue<Message> sharedQueue = new LinkedBlockingQueue<>(10);
//Creating Producer and Consumer Thread
Thread prodThread = new Thread(new Producer(sharedQueue));
Thread consThread1 = new Thread(new Consumer(sharedQueue));
Thread consThread2 = new Thread(new Consumer(sharedQueue));
Thread consThread3 = new Thread(new Consumer(sharedQueue));
//Starting producer and Consumer thread
System.out.println("Producer and consumer threads started \n\n\n---------------------------------------");
prodThread.start();
consThread1.start();
consThread2.start();
consThread1.join();
consThread2.join();
consThread3.start();
}
}
If you want to execute one-by-one, why do you use multiple threads at all? You should just refactor to a single thread.
However, if you want to skip the refactoring, you can just put the consuming threads into a fixed thread pool. In a thread pool, you can set the maximum number of active threads, so you can set the maximum to one and the thread pool will execute the threads one by one.
Another alternative is to create a cyclic barrier where the barrier action is your third thread (it will be invoked after the others). You can execute the first two thread through the cyclic barrier. The barrier can count the finishing threads and will execute the third when the threshold reached. This should meet your goal of wanting for the 3rd consumer thread to wait until the event can be consumed.

java start a thread using isAlive()

I'm new to multithreaded; is this the right way to go about starting a thread?
if(!sesThread.isAlive()) {
try {
sesThread.start();
}catch(IllegalThreadStateException e) { System.out.println("y u start");}
}
premise: caller processes bytearrays and push it to a queue. session thread is to deque and further process them until queue is empty and hence sessions's run() returns
problem: im getting alot of exceptions getting thrown and even so my session thread for some reason has its run() being called twice!
i.e. (start > start > end > end) NOT (start > end > start > end)
Is there some way to synchronize or ensure this "lazy instantiation"-ish mechanism call start only once?
ps. im making a multithreaded UDP socket server aimed at delivery speed, so itd be great to have minimal delay and not some thread.sleep() prior to isAlive()
No you should not use this mechanism.
Your consumer thread should not terminate just because the queue is empty. Threads are expensive to start. You should use a BlockingQueue and have your consumer thread block when the queue is empty.
public class TwoThreads {
public static void main(String args[]) throws InterruptedException {
System.out.println("TwoThreads:Test");
new TwoThreads().test();
}
// The end of the list.
private static final Integer End = -1;
static class Producer implements Runnable {
final BlockingQueue<Integer> queue;
public Producer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
#Override
public void run() {
try {
for (int i = 0; i < 1000; i++) {
queue.add(i);
Thread.sleep(1);
}
// Finish the queue.
queue.add(End);
} catch (InterruptedException ex) {
// Just exit.
}
}
}
static class Consumer implements Runnable {
final BlockingQueue<Integer> queue;
public Consumer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
#Override
public void run() {
boolean ended = false;
while (!ended) {
Integer i = queue.take();
ended = i == End;
System.out.println(i);
}
}
}
public void test() throws InterruptedException {
BlockingQueue<Integer> queue = new LinkedBlockingQueue<>();
Thread pt = new Thread(new Producer(queue));
Thread ct = new Thread(new Consumer(queue));
// Start it all going.
pt.start();
ct.start();
// Wait for it to finish.
pt.join();
ct.join();
}
}
A Thread which is not started is just another object. Calling isAlive() makes no sense. A running thread can be alive, a thread object can't.
Is there some way to synchronize or ensure this "lazy
instantiation"-ish mechanism call start only once?
A thread can be started only once. Calling start() again will lead to IllegalThreadStateException

How to pause running thread and restart same thread when needed?

i want to pause thread which is writing messages in file by iterate message list. When message list is empty i want thread to stop and thread is resumed when message in a list.
I know stop,suspend (),resume methods is deprecated but if thread is continuously in background it consumes cpu. I did lots of googling but can't find proper answer. please any one help me out
Here is my code:
private Thread mFileWriterThread = new Thread() {
#Override
public synchronized void run() {
while (mIsRunning) {
synchronized (mMessageList) {
Iterator it = mMessageList.iterator();
while ((it.hasNext())) {
String message = (String) it.next();
writeToFile(fileOutputStream, message);
mMessageList.remove(message);
}
}
}
}
};
That's what a BlockingQueue exists for. It has a take() method that forces a thread to block until an Object is avalaible. Your problem can be solved with a simple producer-consumer design.
I'm pasting here a minimal snippet taken from the Oracle examples:
class Producer implements Runnable {
private final BlockingQueue queue;
Producer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { queue.put(produce()); }
} catch (InterruptedException ex) { ... handle ...}
}
Object produce() { ... }
}
class Consumer implements Runnable {
private final BlockingQueue queue;
Consumer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { consume(queue.take()); }
} catch (InterruptedException ex) { ... handle ...}
}
void consume(Object x) { ... }
}
Of course Consumer an Producer have to share the queue somehow (just passing it to the constructor as shown in the example will work fine).
You want to use wait() to make the thread block*. And then call notify() to wake up the thread again. Google for "java wait notify" will give you a tutorial.
*Block here mean wait without using any resources, until an other thread wake it up.

Java Threads with Boss-Worker

I have to do schoolwork, and I have some code done, but got some questions:
must create a boss-workers application in java.
I have these classes: Main WorkerThread BossThread Job
Basically what I want to do is, that BossThread holds a BlockingQueue and workers go there and look for Jobs.
Question 1:
At the moment I start 5 WorkingThreads and 1 BossThread.
Main:
Collection<WorkerThread> workers = new ArrayList<WorkerThread>();
for(int i = 1; i < 5; i++) {
WorkerThread worker = new WorkerThread();
workers.add(worker);
}
BossThread thread = new BossThread(jobs, workers);
thread.run();
BossThread:
private BlockingQueue<Job> queue = new ArrayBlockingQueue<Job>(100);
private Collection<WorkerThread> workers;
public BossThread(Set<Job> jobs, Collection<WorkerThread> workers) {
for(Job job : jobs) {
queue.add(job);
}
for(WorkerThread worker : workers) {
worker.setQueue(queue);
}
this.workers = workers;
}
Is this normal, or I should create WorkerThreads in my BossThread ?
Question 2:
As you see I am giving the queue to each WorkerThread , is that reasonable or I could store the queue only in one place?
Question 3:
Must I keep my BossThread running somehow, just to wait if user adds more stuff to queue? And how I keep WorkerThreads running, to look for jobs from queue?
Any overall suggestions or design flaws or suggestions?
public class WorkerThread implements Runnable {
private BlockingQueue<Job> queue;
public WorkerThread() {
}
public void run() {
try {
queue.take().start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void setQueue(BlockingQueue<Job> queue) {
this.queue = queue;
}
}
Firstly, one important mistake I noticed:
BossThread thread = new BossThread(jobs, workers));
thread.run();
Runnables must be passed to a Thread object and threads are started with start, not run. By calling run you get sequential execution on the same thread. So:
Thread thread = new Thread(new BossThread(jobs, workers)));
thread.start();
Secondly, unless you absolutely must use BlockingQueue and explicit threads I would instead use ExecutorService. It neatly encapsulates a blocking work queue and a team of workers (whose size you can set). It's basically what you're doing but much simpler to use:
class Job implements Runnable {
public void run() {
// work
}
}
...
// create thread pool with 5 threads and blocking queue
ExecutorService exec = Executors.newFixedThreadPool(5);
// submit some work
for(int i = 0; i < 10; i++) {
exec.submit(new Job());
}
And that's it! All the put and take stuff is handled by the executor automatically.

IllegalMonitorException using Semaphore and Monitor in Java

I have a project for my "Operating Systems". I need to write 2 programs with java...
write a program that produce Water with 2 method Oxygen and Hydrogen.
method Oxygen produce one Oxygen and method Hydrogen produce one hydrogen. when 2 Hydrogen and one Oxygen was existed H2O created. I must write this with with Semaphores and threads.
Write the above problem with Monitors and Sychronize.
I've writed some code for this but it gives illegal monitor exeption...
please help me to correct it...
This is my code:
// class for implement Thread for oxygen
public class Thread_O implements Runnable {
public void run() {
thread t = new thread();
try {
t.oxygen();
} catch (InterruptedException ex) {
Logger logger = Logger.getLogger(Thread_O.class.getName());
logger.log(Level.SEVERE, null, ex);
}
}
}
// class for implement Thread for Hydrogen
public class Thread_H implements Runnable {
public void run() {
thread t = new thread();
try {
t.Hydrogen();
} catch (InterruptedException ex) {
Logger logger = Logger.getLogger(Thread_H.class.getName());
logger.log(Level.SEVERE, null, ex);
}
}
}
//class for method Oxygen and Hydrogen
public class thread {
Semaphore O = new Semaphore(0, true);
Semaphore H = new Semaphore(0, true);
Semaphore H2O = new Semaphore(0, true);
Semaphore safe = new Semaphore(1, true);
public void oxygen() throws InterruptedException {
safe.wait();
H.wait();
H.wait();
H2O.release();
H2O.release();
Safe.release();
// System.out.println("O2...!");
}
public void Hydrogen() throws InterruptedException {
H.release();
H2O.wait();
// System.out.println("H2...!");
}
}
and in action of Oxygen Button:
Thread th = new Thread(new Thread_O());
th.start();
I'm not going to decode your homework for you, but an IllegalMonitorException is thrown when you're trying to wait() on an object without being synchronized. So to wait for an object called list:
synchronized (list) {
try {
list.wait();
} catch(Throwable t) {
t.printStackTrace();
}
}
You have to understand how the producer/consumer mechanism work.
Here you'll have one consumer thread and two producers.
First you'll have one thread producing oxygen, and other producing hydrogen.
Then, those molecules should be places "somewhere" ok? That "something" is the thing that has to be monitored and synchronized.
So it should go something like this:
class Water {
char [] waterMolecule = new char[3]; // <-- synchronize access to this
char hydrogen(){
return 'H';
}
char oxygen() {
return 'O';
}
void produce() {
Thread t = new Thread( new Runnable() {
synchronize( waterMolecule ) {
waterMolecule[0] = hydrogen();
}
}):
.... produce the others
}
void consume() {
synchronize watermolecule
if waterMolecule is complete
create water and clean out the molecule.
}
}
That's the basic idea.
Just bear in mind that you won't be able to produce another particle of oxigen until the previous one has been consumed.
Also you must always call wait in a while loop
Here's how that wait/synchronize should be coded.
Here's a number of producer/consumer samples.
Although your homework is already due, I'd like to propose CyclicBarrier as the best solution for this scenario.
It allows some kind of rendezvous for the different threads (here: your molecule producers) and triggers the execution of an additional runnable on completition (here: creation of h20).

Categories

Resources