Create a synchronous multithreaded system to determine the total of all integers or fractions in three text files. If a stream is blocked, it must display its name as "LOCKED". Why count only one file (Thread with lock)? What the programs display:Thread-0 Locked!
Thread-2 Locked!
123.321 322099, it's only for one file
import java.io.*;
import java.util.*;
import java.util.concurrent.locks.*;
public class Dispatcher {
public static void main(String[] args) throws InterruptedException {
SumOfDigits sumOfDigits = new SumOfDigits();
Thread thread = new Handler(new File("text.txt"), sumOfDigits);
Thread thread2 = new Handler(new File("text2.txt"), sumOfDigits);
Thread thread3 = new Handler(new File("text3.txt"), sumOfDigits);
thread.start();
thread2.start();
thread3.start();
thread.join();
thread2.join();
thread3.join();
System.out.println(sumOfDigits.resultDouble + " " + sumOfDigits.resultInt);
}
}
class SumOfDigits {
double resultDouble;
int resultInt;
Lock lock = new ReentrantLock();
void sum(File file) {
try (Scanner sc = new Scanner(file)) {
int tempInt = 0;
double tempDouble = 0;
while (sc.hasNext()) {
String num = sc.next();
if (num.contains(".")) {
tempDouble += Double.parseDouble(num);
} else {
tempInt += Integer.parseInt(num);
}
}
boolean flag = lock.tryLock();
if (flag) {
try {
resultDouble += tempDouble;
resultInt += tempInt;
} catch (Exception e) {
} finally {
lock.unlock();
}
} else {
System.out.println(Thread.currentThread().getName() + " Locked!");
}
} catch (Exception e) {
}
}
}
class Handler extends Thread {
File file;
SumOfDigits sumOfDigits;
Handler(File file, SumOfDigits sumOfDigits) {
this.file = file;
this.sumOfDigits = sumOfDigits;
}
#Override
public void run() {
sumOfDigits.sum(file);
}
}
The ReentrantLock maintains a count of how many times it has been locked by the current thread. This count is decremented every time you call unlock() and the lock is release when the count reaches zero. Thus, to unlock the lock, you must call unlock() as many times as you have called lock() or tryLock().
In your code, you call tryLock() and if it is successful, you then call lock() inside the try/finally block and then you call unlock() once.
The first thread to lock the ReentrantLock will thus increment the count to two but only decrement the count to one, so the lock is never released. Therefore, no other thread can ever acquire the lock.
You should use tryLock() or lock() to the lock the ReentrantLock, not both.
Related
The question is to create 3 threads, one prints a random number every second, if the number is even a second thread squares it and if it odd a third thread cubes it. This should occur a given number of times(in my code it is infinite, will edit that out later). My issue is that after the first iteration(i.e. a random number is created, the correct thread wakes up and does its operation) the second/third threads don't wake up after notifyAll() is called again. My code is shown below with sample output. I've added a few print statements for debugging purposes:
package com.company;
import java.util.*;
class RandomNumber implements Runnable{
int randomNum = 0;
Random rand = new Random();
boolean flag = false;
public RandomNumber() {
Thread newThread = new Thread(this,"Random Number");
newThread.start();
}
#Override
public synchronized void run()
{
while(flag == false) {
System.out.println("random num thread");
try {
randomNum = rand.nextInt(100) + 1;
System.out.println(randomNum);
flag = true;
notifyAll();
//System.out.println(flag);
Thread.sleep(1000);
} catch (Exception e) {
System.out.println("Exception Caught");
}
}
}
}
class SquareNumber implements Runnable{
RandomNumber randomNumOb;
public SquareNumber(RandomNumber randNumObject){
this.randomNumOb = randNumObject;
Thread squareThread = new Thread(this, "Square thread");
squareThread.start();
}
#Override
public synchronized void run() {
System.out.println("square thread before while");
while(randomNumOb.flag == true) {
System.out.println("square thread");
if (randomNumOb.randomNum % 2 == 0)
{
System.out.println("Number is even so square of " + randomNumOb.randomNum + " is: " + (randomNumOb.randomNum * randomNumOb.randomNum));
try {
randomNumOb.flag = false;
wait();
}catch(Exception e){
System.out.println("Exception caught");
}
}
else {
try {
System.out.println("inside square else");
wait();
} catch (Exception e) {
System.out.println("Exception Caught");
}
}
}
System.out.println("square thread after while");
}
}
class CubeNumber implements Runnable{
RandomNumber randomNumOb;
public CubeNumber(RandomNumber randNumObject){
this.randomNumOb = randNumObject;
Thread squareThread = new Thread(this, "Square thread");
squareThread.start();
}
#Override
public synchronized void run() {
System.out.println("cube thread before while");
while(randomNumOb.flag == true) {
System.out.println("cube thread");
if (randomNumOb.randomNum % 2 == 1) {
System.out.println("Number is odd so cube of " + randomNumOb.randomNum + " is: " + (randomNumOb.randomNum * randomNumOb.randomNum * randomNumOb.randomNum));
try {
randomNumOb.flag = false;
wait();
}catch (Exception e){
}
}
else {
try {
System.out.println("inside cube else");
//randomNumOb.flag = false;
wait();
} catch (Exception e) {
System.out.println("Exception Caught");
}
}
}
System.out.println("cube thread after while");
}
}
public class Main {
public static void main(String[] args) {
RandomNumber random = new RandomNumber();
SquareNumber square = new SquareNumber(random);
CubeNumber cube = new CubeNumber(random);
}
}
Sample output:
random num thread
81
square thread before while
square thread
inside square else
cube thread before while
cube thread
Number is odd so cube of 81 is: 531441
random num thread
68
It seems like neither the square or cube thread wakes up after this and can't figure out why. Any help would be appreciated.
For locking and wait/notify to work there needs to be a shared lock.
There is an "intrinsic lock" which is baked into each object. The lock works as a communications hub for wait and notify. Putting synchronized on an instance method means that a thread calling that method acquires the intrinsic lock on the instance when it enters the method, and releases the intrinsic lock when it leaves. The wait/notify/notifyAll methods can be called only by a thread holding the intrinsic lock.
When a thread calls wait, that releases the lock and the thread goes dormant until it receives a notification (or gets interrupted). The lock keeps track of which threads are currently waiting on it, that's called the waitset.
When a thread calls notify, that tells the scheduler to pick a thread from the lock's waitset and send it a notification. The notifyAll method is the same except it wakes up all the other threads in the waitset.
That is how locking determines which waiting thread gets notified.
So in the posted code, each of these Runnables acquires its own intrinsic lock and there is no sharing. the wakeup notification has to be caused by another thread that has acquired the lock that the waiting thread called wait on.
Here you could create a common lock in the entrypoint class
final Object lock = new Object(); // value referenced by lock must not change
and pass it into the different Runnables in the constructor such as:
public SquareNumber(RandomNumber randNumObject, Object lock){
this.lock = lock;
...
so they use the same lock. Then change wait and notify method calls to use that shared lock object, and change the synchronized methods to synchronized blocks that pass in the lock.
Btw about the sleep added to the RandomNumber runnable: the notifyAll doesn't take effect until the current thread releases the lock (since each waiting thread has to acquire the lock in order to leave the wait method). Sleeping here doesn't do anything to give the notification time to work, it just prevents anything from happening.
CubeNumber and SquareNumber both wait all for notifications on their own object - not for notifications on the random object. So they never get notified.
package com.company;
import java.util.*;
class RandomNumber implements Runnable{
int randomNum = 0;
Random rand = new Random();
boolean flag = false;
public RandomNumber() {
Thread newThread = new Thread(this,"Random Number");
newThread.start();
}
#Override
public void run()
{
while(flag == false) {
System.out.println("random num thread");
try {
randomNum = rand.nextInt(100) + 1;
System.out.println(randomNum);
flag = true;
synchronized(this) {
notifyAll();
}
//System.out.println(flag);
Thread.sleep(1000);
} catch (Exception e) {
System.out.println("Exception Caught");
}
}
class CubeNumber implements Runnable{
RandomNumber randomNumOb;
public CubeNumber(RandomNumber randNumObject){
this.randomNumOb = randNumObject;
Thread squareThread = new Thread(this, "Square thread");
squareThread.start();
}
#Override
public synchronized void run() {
System.out.println("cube thread before while");
while(randomNumOb.flag == true) {
System.out.println("cube thread");
if (randomNumOb.randomNum % 2 == 1) {
System.out.println("Number is odd so cube of " + randomNumOb.randomNum + " is: " + (randomNumOb.randomNum * randomNumOb.randomNum * randomNumOb.randomNum));
try {
randomNumOb.flag = false;
synchronised(randomNumOb) {
randomNumOb.wait();
}
}catch (Exception e){
}
}
else {
try {
System.out.println("inside cube else");
//randomNumOb.flag = false;
wait();
} catch (Exception e) {
System.out.println("Exception Caught");
}
}
}
System.out.println("cube thread after while");
}
same with the square version.
But the added problem is that you have no guaranty that both the cube and the square methods will run within the sleep second of randomnumber.
Possibly a sempahor might be of use here.
The main class trying to create 4 threads
After running the threads, each thread tries to lock. And when one thread gets the lock, the rest will wait to unlock.
In my case, once Thread 0 found that the resource is locked, and then Thread 0 went in the wait state, then why again Thread 0 tries to lock the resource.
package com.test.thread;
public class LockImplementation {
public static void main(String[] args) {
MyNewThread myThread1 = new MyNewThread(1);
MyNewThread myThread2 = new MyNewThread(2);
MyNewThread myThread3 = new MyNewThread(3);
MyNewThread myThread4 = new MyNewThread(3);
myThread1.start();
myThread2.start();
myThread3.start();
myThread4.start();
}
}
class Lock {
private boolean isLocked = false;
private Thread lockingThread = null;
int count = 0;
public synchronized void lock() throws InterruptedException {
if (isLocked) {
System.out.println("trying to lock by thread " +
lockingThread.getName());
wait();
}
System.out.println("Locked by thread " +
Thread.currentThread().getName());
isLocked = true;
lockingThread = Thread.currentThread();
}
public synchronized void unLock() {
if (this.lockingThread != Thread.currentThread()) {
throw new IllegalMonitorStateException("Calling thread has not locked this lock");
}
isLocked = false;
lockingThread = null;
notify();
}
}
class MyNewThread extends Thread {
int thNo;
private static Lock lock;
public MyNewThread(int thNo) {
Thread.currentThread().setName(thNo + "");
this.thNo = thNo;
lock = new Lock();
}
#Override
public void run() {
System.out.println("start running thread no " +
Thread.currentThread().getName());
try {
lock.lock();
Thread.sleep(10000);
lock.unLock();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end running thread no " +
Thread.currentThread().getName());
}
}
Why is the same thread trying to lock the resource?
This happens because when first time you enter lock method you set your locking thread as first that enters it. Next threads when call lock() see that isLocked is true and wait, but locking thread still the same and it doesn't update.
I have a program with this general structure:
init
create CyclicBarrier
initialise all threads, attaching to barrier
*start all threads*
wait for join
display stats
*start all threads*
perform calculation
await barrier
My problem is I need the threads' run() method to keep looping until a certain condition is met, but pausing after every iteration to let all threads synchronise.
I've already tried attaching a Runnable method to the barrier, but this ends up requiring the recreation and restarting of each thread, which isn't a very good solution.
I've also tried using the CyclicBarrier's reset() method, but this just seems to cause errors on the existing threads, even when executed after all threads have completed.
My question is:
-Is it possible to 'reset' a barrier and have all the barrier's threads follow the same conditions as they did before the first invocations of await()?
-Or is there another method I should be using to achieve this?
Thanks in advance
The barrier.wait() will suspend the threads. The barrier is already in the main thread, it does not need another. In your algorithm above you show the threads being restarted after displaying stats. You should not need to do this. If the recently awakened threads are in a loop they will go back into the barrier.wait() again.
Following #Totoro's answer, below is a little bit of example code which also incorporates the requirement "I need the threads' run() method to keep looping until a certain condition is met, pausing after every iteration to let all threads synchronise". That makes it complex pretty quick, but hopefully the program output will clarify the example code (or I should just make better examples).
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public class BarrierCalc implements Runnable {
public static final int CALC_THREADS = 3;
private static final AtomicBoolean runCondition = new AtomicBoolean();
private static final AtomicBoolean stopRunning = new AtomicBoolean();
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(CALC_THREADS + 1);
for (int i = 0; i < CALC_THREADS; i++) {
new Thread(new BarrierCalc(barrier)).start();
}
try {
runCondition.set(true);
barrier.await();
showln(0, "STATS!");
barrier.await();
showln(0, "start looping 1");
Thread.sleep(200);
runCondition.set(false);
showln(0, "stop looping 1");
barrier.await();
runCondition.set(true);
barrier.await();
showln(0, "start looping 2");
Thread.sleep(100);
runCondition.set(false);
showln(0, "stop looping 2");
barrier.await();
stopRunning.set(true);
showln(0, "finishing");
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}
private static final AtomicInteger calcId = new AtomicInteger();
private CyclicBarrier barrier;
private int id;
public BarrierCalc(CyclicBarrier barrier) {
this.barrier = barrier;
id = calcId.incrementAndGet();
}
public void run() {
showln(id, "waiting for start");
try {
barrier.await(); // display stats
barrier.await(); // start running
int loopNumber = 0;
while (!stopRunning.get()) {
showln(id, "looping " + (++loopNumber));
while (runCondition.get()) {
Thread.sleep(10); // simulate looping
}
showln(id, "synchronizing " + loopNumber);
barrier.await();
showln(id, "synchronized " + loopNumber);
// give main thread a chance to set stopCondition and runCondition
barrier.await();
}
showln(id, "finished");
} catch (Exception e) {
e.printStackTrace();
}
}
private static final long START_TIME = System.currentTimeMillis();
public static void showln(int id, String msg) {
System.out.println((System.currentTimeMillis() - START_TIME) + "\t ID " + id + ": " + msg);
}
}
Keep in mind that program output might not be in the order expected: threads that are writing at the same time to one synchronized output (System.out) are given write-access in random order.
You can take a look at my example where I played with CyclicBarrier.Here each worker makes some calculation and at the barrier the condition is checked. If it meets the condition than all workers stop calculations, otherwise they continue:
class Solver {
private static final int REQUIRED_AMOUNT = 100;
private static final int NUMBER_OF_THREADS = 4;
AtomicInteger atomicInteger = new AtomicInteger();
AtomicBoolean continueCalculation = new AtomicBoolean(true);
final CyclicBarrier barrier;
public static void main(String[] args) {
new Solver();
}
class Worker implements Runnable {
int workerId;
Worker(int workerId) {
this.workerId = workerId;
}
public void run() {
try {
while(continueCalculation.get()) {
calculate(workerId);
barrier.await();
}
} catch (Exception ex) {
System.out.println("Finishing " + workerId);
}
}
}
public Solver() {
Runnable barrierAction = () -> {
if (done()) {
continueCalculation.set(false);
}
};
barrier = new CyclicBarrier(NUMBER_OF_THREADS, barrierAction);
List<Thread> threads = new ArrayList(NUMBER_OF_THREADS);
for (int i = 0; i < NUMBER_OF_THREADS; i++) {
Thread thread = new Thread(new Worker(i));
threads.add(thread);
thread.start();
}
}
private void calculate(int workerId) throws InterruptedException {
// Some long-running calculation
Thread.sleep(2000L);
int r = new Random().nextInt(12);
System.out.println("Worker #" + workerId + " added " + r +" = " + atomicInteger.addAndGet(r));
}
private boolean done() {
int currentResult = atomicInteger.get();
boolean collected = currentResult >= REQUIRED_AMOUNT;
System.out.println("=======================================================");
System.out.println("Checking state at the barrier: " + currentResult);
if (collected) {
System.out.println("Required result is reached");
}
System.out.println("=======================================================");
return collected;
}
}
Below Room is the class which lets threads enter and exit from a room. Orchestrate_enque_deque is the class that will help thread enter and then do the increment of synchronized variable and wait till all the thread finish.
What I am supposed to do :
The last thread to finish will call the exit handler. The exit handler will then again notify all the thread to enter to next room and again continue this until the last room.
My question :
How can I know when is the last thread executed?
When room 0 is entered 13 threads are created. All 13 thread increment() the shared variable. Threads must wait till all the thread have finished calculation. Now how can I know that all the thread have finished calculation.
Inside the funcition work of Orchestrate_enque_deque
increase();
System.out.println(count);
while(roomobj.enter_room){
cond.await();
System.out.println("now before signal all");
}
Each thread increase and wait and is never signaled to wake up.
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Rooms{
int room;
boolean enter_room = true;
int which_room=0;
public interface Handler{
void onEmpty() throws InterruptedException;
}
public Rooms(int m){
this.room = m;
}
public void enter(int i){
System.out.println("room.enter "+ i );
if(which_room == i) {
enter_room = true;
}
}
public boolean exit(){
if(room < which_room)
return true;
else
{
return false;
}
}
public void setExitHandler(int i, Rooms.Handler h) throws InterruptedException {
h.onEmpty();
}
}
class Orchestrate_enque_deque implements Rooms.Handler{
int count = 0;
final Lock lock = new ReentrantLock();
final Condition cond = lock.newCondition();
Rooms roomobj;
int which_room = 0;
int room_no;
Rooms.Handler handler;
Orchestrate_enque_deque(int room_no){
this.room_no = room_no;
roomobj = new Rooms(room_no);
}
public boolean when_to_exit(){
return roomobj.exit();
}
public void increase(){
for(int i =0;i <100;i++){
count++;
}
}
public void work() throws InterruptedException{
lock.lock();
//while()
// wait till all thread finish job in room.
while(roomobj.enter_room == false)
cond.await();
roomobj.enter(which_room);
try{
if(which_room >0 && which_room < room_no){
System.out.println("orchestrate work : which_room" + which_room );
cond.signalAll();
}
increase();
System.out.println(count);
while(roomobj.enter_room){
cond.await();
System.out.println("now before signal all");
}
//roomobj.setExitHandler(i, h);
}finally{
// roomobj.setExitHandler(i, handler);
lock.unlock();
}
}
public void onEmpty() throws InterruptedException {
roomobj.enter_room = false;
which_room++;
System.out.println("inside onEmpty : which_room after adding" + which_room);
}
}
class Worker extends Thread{
Orchestrate_enque_deque obj;
public Worker(Orchestrate_enque_deque obj){
this.obj = obj;
}
public void run(){
try {
while(!obj.when_to_exit()){
obj.work();
//System.out.println(" I am thread doing run with id "+Thread.currentThread().getId() );
obj.onEmpty();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Simulate{
public static void main(String args[]) throws InterruptedException {
int NO_OF_THREADS = 13;
Orchestrate_enque_deque Orchestrate_obj = new Orchestrate_enque_deque(4);
Worker[] worker_obj = new Worker[NO_OF_THREADS];
for(int i = 0; i < NO_OF_THREADS;i++){
worker_obj[i] = new Worker(Orchestrate_obj);
worker_obj[i].start();
}
for(int j = 0; j < NO_OF_THREADS;j++){
worker_obj[j].join();
}
}
}
I would look into the CompletionService Api provided by in java.util.concurrent
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CompletionService.html
I want to write program using multithreading wait and notify methods in Java.
This program has a stack (max-length = 5). Producer generate number forever and put it in the stack, and consumer pick it from stack.
When stack is full producer must wait and when stack is empty consumers must wait.
The problem is that it runs just once, I mean once it produce 5 number it stops but i put run methods in while(true) block to run nonstop able but it doesn't.
Here is what i tried so far.
Producer class:
package trail;
import java.util.Random;
import java.util.Stack;
public class Thread1 implements Runnable {
int result;
Random rand = new Random();
Stack<Integer> A = new Stack<>();
public Thread1(Stack<Integer> A) {
this.A = A;
}
public synchronized void produce()
{
while (A.size() >= 5) {
System.out.println("List is Full");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
result = rand.nextInt(10);
System.out.println(result + " produced ");
A.push(result);
System.out.println(A);
this.notify();
}
#Override
public void run() {
System.out.println("Producer get started");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
while (true) {
produce();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
And the consumer:
package trail;
import java.util.Stack;
public class Thread2 implements Runnable {
Stack<Integer> A = new Stack<>();
public Thread2(Stack<Integer> A) {
this.A = A;
}
public synchronized void consume() {
while (A.isEmpty()) {
System.err.println("List is empty" + A + A.size());
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.err.println(A.pop() + " Consumed " + A);
this.notify();
}
#Override
public void run() {
System.out.println("New consumer get started");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
while (true) {
consume();
}
}
}
and here is the main method:
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
Thread1 thread1 = new Thread1(stack);// p
Thread2 thread2 = new Thread2(stack);// c
Thread A = new Thread(thread1);
Thread B = new Thread(thread2);
Thread C = new Thread(thread2);
A.start();
B.start();
C.start();
}
I think it will be better for understanding and dealing with synchronisation in general if you try to separate three things which are currently mixed:
Task which is going to do the actual job. Names for classes Thread1 & Thread2 are misleading. They are not Thread objects, but they are actually jobs or tasks implementing Runnable interface you are giving to Thread objects.
Thread object itself which you are creating in main
Shared object which encapsulates synchronised operations/logic on a queue, a stack etc. This object will be shared between tasks. And inside this shared object you will take care of add/remove operations (either with synchronized blocks or synchronized methods). Currently (as it was pointed out already), synchronization is done on a task itself (i.e. each task waits and notifies on its own lock and nothing happens). When you separate concerns, i.e. let one class do one thing properly it will eventually become clear where is the problem.
Your consumer and you producer are synchronized on different objects and do not block each other. If this works, I daresay it's accidental.
Read up on java.util.concurrent.BlockingQueue and java.util.concurrent.ArrayBlockingQueue. These provide you with more modern and easier way to implement this pattern.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html
You should synchronize on the stack instead of putting it at the method level try this code.
Also don't initalize the stack in your thread classes anyways you are passing them in the constructor from the main class, so no need of that.
Always try to avoid mark any method with synchronized keyword instead of that try to put critical section of code in the synchronized block because the more size of your synchronized area more it will impact on performance.
So, always put only that code into synchronized block that need thread safety.
Producer Code :
public void produce() {
synchronized (A) {
while (A.size() >= 5) {
System.out.println("List is Full");
try {
A.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
result = rand.nextInt(10);
System.out.println(result + " produced ");
A.push(result);
System.out.println("stack ---"+A);
A.notifyAll();
}
}
Consumer Code :
public void consume() {
synchronized (A) {
while (A.isEmpty()) {
System.err.println("List is empty" + A + A.size());
try {
System.err.println("wait");
A.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.err.println(A.pop() + " Consumed " + A);
A.notifyAll();
}
}
Try this:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class CircularArrayQueue<T> {
private volatile Lock rwLock = new ReentrantLock();
private volatile Condition emptyCond = rwLock.newCondition();
private volatile Condition fullCond = rwLock.newCondition();
private final int size;
private final Object[] buffer;
private volatile int front;
private volatile int rare;
/**
* #param size
*/
public CircularArrayQueue(int size) {
this.size = size;
this.buffer = new Object[size];
this.front = -1;
this.rare = -1;
}
public boolean isEmpty(){
return front == -1;
}
public boolean isFull(){
return (front == 0 && rare == size-1) || (front == rare + 1);
}
public void enqueue(T item){
try {
// get a write lock
rwLock.lock();
// if the Q is full, wait the write lock
if(isFull())
fullCond.await();
if(rare == -1){
rare = 0;
front = 0;
} else if(rare == size - 1){
rare = 0;
} else {
rare ++;
}
buffer[rare] = item;
//System.out.println("Added\t: " + item);
// notify the reader
emptyCond.signal();
} catch(InterruptedException e){
e.printStackTrace();
} finally {
// unlock the write lock
rwLock.unlock();
}
}
public T dequeue(){
T item = null;
try{
// get the read lock
rwLock.lock();
// if the Q is empty, wait the read lock
if(isEmpty())
emptyCond.await();
item = (T)buffer[front];
//System.out.println("Deleted\t: " + item);
if(front == rare){
front = rare = -1;
} else if(front == size - 1){
front = 0;
} else {
front ++;
}
// notify the writer
fullCond.signal();
} catch (InterruptedException e){
e.printStackTrace();
} finally{
// unlock read lock
rwLock.unlock();
}
return item;
}
}
You can use Java's awesome java.util.concurrent package and its classes.
You can easily implement the producer consumer problem using the
BlockingQueue. A BlockingQueue already supports operations that wait
for the queue to become non-empty when retrieving an element, and wait
for space to become available in the queue when storing an element.
Without BlockingQueue, every time we put data to queue at the producer
side, we need to check if queue is full, and if full, wait for some
time, check again and continue. Similarly on the consumer side, we
would have to check if queue is empty, and if empty, wait for some
time, check again and continue. However with BlockingQueue we don’t
have to write any extra logic than to just add data from Producer and
poll data from Consumer.
Read more From:
http://javawithswaranga.blogspot.in/2012/05/solving-producer-consumer-problem-in.html
http://www.javajee.com/producer-consumer-problem-in-java-using-blockingqueue
use BlockingQueue,LinkedBlockingQueue this was really simple.
http://developer.android.com/reference/java/util/concurrent/BlockingQueue.html
package javaapplication;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ProducerConsumer {
public static Object lock = new Object();
public static Stack stack = new Stack();
public static void main(String[] args) {
Thread producer = new Thread(new Runnable() {
int i = 0;
#Override
public void run() {
do {
synchronized (lock) {
while (stack.size() >= 5) {
try {
lock.wait();
} catch (InterruptedException e) {
}
}
stack.push(++i);
if (stack.size() >= 5) {
System.out.println("Released lock by producer");
lock.notify();
}
}
} while (true);
}
});
Thread consumer = new Thread(new Runnable() {
#Override
public void run() {
do {
synchronized (lock) {
while (stack.empty()) {
try {
lock.wait();
} catch (InterruptedException ex) {
Logger.getLogger(ProdCons1.class.getName()).log(Level.SEVERE, null, ex);
}
}
while(!stack.isEmpty()){
System.out.println("stack : " + stack.pop());
}
lock.notifyAll();
}
} while (true);
}
});
producer.start();
consumer.start();
}
}
Have a look at this code example:
import java.util.concurrent.*;
import java.util.Random;
public class ProducerConsumerMulti {
public static void main(String args[]){
BlockingQueue<Integer> sharedQueue = new LinkedBlockingQueue<Integer>();
Thread prodThread = new Thread(new Producer(sharedQueue,1));
Thread consThread1 = new Thread(new Consumer(sharedQueue,1));
Thread consThread2 = new Thread(new Consumer(sharedQueue,2));
prodThread.start();
consThread1.start();
consThread2.start();
}
}
class Producer implements Runnable {
private final BlockingQueue<Integer> sharedQueue;
private int threadNo;
private Random rng;
public Producer(BlockingQueue<Integer> sharedQueue,int threadNo) {
this.threadNo = threadNo;
this.sharedQueue = sharedQueue;
this.rng = new Random();
}
#Override
public void run() {
while(true){
try {
int number = rng.nextInt(100);
System.out.println("Produced:" + number + ":by thread:"+ threadNo);
sharedQueue.put(number);
Thread.sleep(100);
} catch (Exception err) {
err.printStackTrace();
}
}
}
}
class Consumer implements Runnable{
private final BlockingQueue<Integer> sharedQueue;
private int threadNo;
public Consumer (BlockingQueue<Integer> sharedQueue,int threadNo) {
this.sharedQueue = sharedQueue;
this.threadNo = threadNo;
}
#Override
public void run() {
while(true){
try {
int num = sharedQueue.take();
System.out.println("Consumed: "+ num + ":by thread:"+threadNo);
Thread.sleep(100);
} catch (Exception err) {
err.printStackTrace();
}
}
}
}
Notes:
Started one Producer and two Consumers as per your problem statement
Producer will produce random numbers between 0 to 100 in infinite loop
Consumer will consume these numbers in infinite loop
Both Producer and Consumer share lock free and Thread safe LinkedBlockingQueue which is Thread safe. You can remove wait() and notify() methods if you use these advanced concurrent constructs.
Seems like you skipped something about wait(), notify() and synchronized.
See this example, it should help you.