Does ReentrantReadWriteLock read while writeLock locked? - java

I research ReentrantReadWriteLock.
I write simple code for test(I know that use Thread.sleep() can not guarantee predictable result but I think that I am lucky:)):
public class RWLock {
private static String val = "old";
private static ReadWriteLock lock = new ReentrantReadWriteLock();
private static long time = System.currentTimeMillis();
public void read() {
try {
lock.readLock().lock();
System.out.println("read " + val +" - "+(System.currentTimeMillis()-time));
Thread.sleep(300);
} catch (InterruptedException e) {
} finally {
lock.readLock().unlock();
}
}
public void write() {
try {
lock.writeLock().lock();
val = "new";
System.out.println("write " + val+" - "+(System.currentTimeMillis()-time));
Thread.sleep(10000);
} catch (InterruptedException e) {
} finally {
lock.writeLock().unlock();
}
}
}
class Tester {
public static void main(String[] args) throws InterruptedException {
new MyThreadRead().start();
Thread.sleep(400);
new MyThreadWrite().start();
}
}
class MyThreadRead extends Thread {
#Override
public void run() {
for (int i = 0; i < 10; i++) {
new RWLock().read();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
}
}
}
class MyThreadWrite extends Thread {
#Override
public void run() {
new RWLock().write();
}
}
output:
read old - 0
write new - 401
read new - 10401
read new - 10902
read new - 11402
read new - 11902
read new - 12402
read new - 12902
read new - 13402
read new - 13902
read new - 14402
10401 - 401 == 10000
10000 it is time of writing.
As I understood second read thread cannot finish before writing. Thus writing and second reading performs in parallel. It is not predictable behaviour for me.
What do you think about it?

Maybe you have more sleep() calls than you realize. The sleep calls in MyThreadRead#run() and in RWLock()#read() add up to 500 ms. So here's what's happening.
At T=0, the reader thread grabs the read lock and sleeps for 300ms.
At T=300, the reader releases the lock, and then sleeps for another 200ms.
At T=400, the writer grabs the write lock and sleeps for ten seconds,
At T=500, the reader tries to grab the read lock, but it is blocked by the writer.
At T=10400, the writer gives up the lock, and then the reader gets to go round
its loop nine more times.
P.S.: Move your lock() calls out of the try/finally statements. E.g.,
...lock()
try {
...
} finally {
...unlock();
}
That way, if the lock() call throws an exception, the unlock() will not be called.

Related

How does Java non-fair ReentrantReadWriteLock really work?

I have written the following test code in Java using ReentrantReadWriteLock to understand the difference between fair and non-fair mode. However, I see in both modes the result and output is always the same. It seems it's always working in fair mode. Can anybody explain in which case fair and non-fair mode will result in different behaviors?
package lockTest;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class MyLockTest {
static private ReadWriteLock myLock = new ReentrantReadWriteLock(false);
public class Reader extends Thread {
int val_;
public Reader(int val) {
val_ = val;
}
public void run() {
if (val_ > 0) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
myLock.readLock().lock();
System.out.println(Thread.currentThread().getName() + ": Reader inside critical section - val: " + val_ + "-----");
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
myLock.readLock().unlock();
}
}
public class Writer extends Thread {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
myLock.writeLock().lock();
System.out.println(Thread.currentThread().getName() + ": Writer inside critical section *****");
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
myLock.writeLock().unlock();
}
}
public static void main(String[] args) {
MyLockTest test1 = new MyLockTest();
MyLockTest.Reader reader1 = test1.new Reader(0);
MyLockTest.Writer writer1 = test1.new Writer();
MyLockTest.Reader reader2 = test1.new Reader(1);
reader2.start();
writer1.start();
reader1.start();
}
}
The output is always:
Thread-0: Reader inside critical section - val: 0-----
Thread-1: Writer inside critical section *****
Thread-2: Reader inside critical section - val: 1-----
The output above is what I expect to see when I change Lock creation to fair mode:
static private ReadWriteLock myLock = new ReentrantReadWriteLock(true);
For non-fair mode I would expect to see the following output:
Thread-0: Reader inside critical section - val: 0-----
Thread-2: Reader inside critical section - val: 1-----
Thread-1: Writer inside critical section *****
Using "fair" versus "non-fair" mode affects how the lock is assigned to threads in case of contention.
From the Javadoc for ReentrantReadWriteLock: using the "non-fair" mode, the order of entry to the read and write lock is unspecified, while using the "fair" mode, threads contend for entry using an approximately arrival-order policy.
We can see how using fair/non-fair affects program execution by having some thread contend over the same lock; see the program below.
Running the sample code, a ReentrantWriteLock is contended by different threads; after 1000 lock operations, we dump how many times each thread acquired the lock.
In case USE_FAIR=false is used, counts are random, and a possible output is:
Thread thread-B finished, count=920
Thread thread-A finished, count=79
Thread thread-D finished, count=0
Thread thread-C finished, count=0
in case USE_FAIR=true is used, the output is always like
Thread thread-D finished, count=249
Thread thread-A finished, count=250
Thread thread-C finished, count=250
Thread thread-B finished, count=250
Sample code
package sample1;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class UseLock {
public static void main(String[] args) {
UseLock o = new UseLock();
o.go();
}
private void go() {
TotalPermits tp = new TotalPermits();
tp.lock.writeLock().lock();
Contender a = new Contender(tp, "thread-A");
Contender b = new Contender(tp, "thread-B");
Contender c = new Contender(tp, "thread-C");
Contender d = new Contender(tp, "thread-D");
a.start();
b.start();
c.start();
d.start();
tp.lock.writeLock().unlock();
}
}
class TotalPermits {
private static final boolean USE_FAIR = true;
private int count = 1_000;
ReentrantReadWriteLock lock = new ReentrantReadWriteLock(USE_FAIR);
public boolean get() {
try {
lock.writeLock().lock();
try {
Thread.sleep(1);
} catch (InterruptedException e) { }
return --count>0;
} finally {
lock.writeLock().unlock();
}
}
}
class Contender extends Thread {
private int count = 0;
final String name;
final TotalPermits tp;
Contender(TotalPermits tp, String name) {
this.tp = tp;
this.name = name;
}
#Override
public void run() {
while ( tp.get() ) {
count++;
}
System.out.printf("Thread %s finished, count=%d%n", name, count);
}
}
Note:
The sample code above uses a "write" lock, which can only be held by one thread at a time. So we can use that to divide N permits across the contenders. On the other hand, the "read" lock can be held by multiple threads, as long as none is holding the write lock.

Java FileWriter thread safety [duplicate]

This question already has answers here:
Threads and file writing
(6 answers)
Closed 9 years ago.
i have 20 threads that write with the println() function on a file called results.txt. How can i synchronize them all?
I note every time my program run i have different number of lines of text in results.txt.
Thank you.
Access the file through a class that contains a synchronized method to write to the file. Only one thread at a time will be able to execute the method.
I think that Singleton pattern would fit for your problem:
package com.test.singleton;
public class Singleton {
private static final Singleton inst= new Singleton();
private Singleton() {
super();
}
public synchronized void writeToFile(String str) {
// Do whatever
}
public static Singleton getInstance() {
return inst;
}
}
Every time you need to write to your file, you only would have to call:
Singleton.getInstance().writeToFile("Hello!!");
Duplicate question ... duplicate answer. As I said here:
If you can hold your file as a FileOutputStream you can lock it like this:
FileOutputStream file = ...
....
// Thread safe version.
void write(byte[] bytes) {
try {
boolean written = false;
do {
try {
// Lock it!
FileLock lock = file.getChannel().lock();
try {
// Write the bytes.
file.write(bytes);
written = true;
} finally {
// Release the lock.
lock.release();
}
} catch ( OverlappingFileLockException ofle ) {
try {
// Wait a bit
Thread.sleep(0);
} catch (InterruptedException ex) {
throw new InterruptedIOException ("Interrupted waiting for a file lock.");
}
}
} while (!written);
} catch (IOException ex) {
log.warn("Failed to lock " + fileName, ex);
}
}
You are intend to write data into one file. So if you try to lock the whole file, it'd better to use a single thread to do this job. Although you spawn 20 threads, but there is only one of them is running every time you call the method, the others are just waiting for the lock.
I recommend you use RandomAccessFile to write data to your file. Then each thread can write some unique data into to the file without locking the whole file.
Some demo code as following
try {
final RandomAccessFile file = new RandomAccessFile("/path/to/your/result.txt", "rw");
final int numberOfThread = 20;
final int bufferSize = 512;
ExecutorService pool = Executors.newFixedThreadPool(numberOfThread);
final AtomicInteger byteCounter = new AtomicInteger(0);
final byte[] yourText = "Your data".getBytes();
for (int i = 0; i < yourText.length; i++) {
pool.submit(new Runnable() {
#Override
public void run() {
int start = byteCounter.getAndAdd(bufferSize);
int chunkSize = bufferSize;
if (start + bufferSize > yourText.length) {
chunkSize = yourText.length - start;
}
byte[] chunkData = new byte[chunkSize];
System.arraycopy(yourText, start, chunkData, 0, chunkSize);
try {
file.write(chunkData);
} catch (IOException e) {
//exception handle
}
}
});
}
file.close();
} catch (Exception e) {
//clean up
}

Why there is a deadlock for given many readers and writers [duplicate]

This question already has an answer here:
Semaphore solution to reader-writer: order between updating reader count and waiting or signaling on read/write binary semaphore?
(1 answer)
Closed 4 years ago.
I'm practicing readers and writers problem and come up with the following solution. However, the program blocks itself after printing out the following results.
$ Read content: planets
My idea is a modified version of the first solution. With 2 semaphores, one called readMutex ensuring only one read thread to update numOfReaders at a time, while the other semaphore called accessToResource ensuring that when readers are reading content, the writer should wait. Here's my code.
import java.util.concurrent.Semaphore;
public class ReadersAndWriters {
public static final Semaphore accessToResource = new Semaphore(1, true);
public static final Semaphore readMutex = new Semaphore(1, true);
public static String content = "planets";
public static int numOfReaders;
static class Reader extends Thread {
void read() {
try {
readMutex.acquire();
numOfReaders++;
if (numOfReaders == 1) {
accessToResource.acquire();
}
readMutex.release();
// read content, not a critical section
System.out.println("Read content:\t" + content);
readMutex.acquire();
numOfReaders--;
if (numOfReaders <= 0) {
accessToResource.release();
}
readMutex.release();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void run() {
read();
}
}
static class Writer extends Thread {
String text;
Writer(String text) {
this.text = text;
}
void write() {
try {
readMutex.acquire();
accessToResource.acquire();
// critical section
content = text;
System.out.println("Content changed:\t" + content);
// end of critical section
accessToResource.release();
readMutex.release();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void run() {
write();
}
}
public static void main(String[] args) {
Reader t1 = new Reader();
Reader t2 = new Reader();
Writer t3 = new Writer("stars");
Reader t4 = new Reader();
Writer t5 = new Writer("restaurant at the end of universe");
Reader t6 = new Reader();
Reader t7 = new Reader();
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
t7.start();
}
}
When one Reader has acquired accessToResource and try to acquire readMutex:
if (numOfReaders == 1) {
accessToResource.acquire();
}
readMutex.release();
System.out.println("Read content:\t" + content);
readMutex.acquire(); // -------> here
while another Writter has acquired readMutex and try to acquire accessToResource:
readMutex.acquire();
accessToResource.acquire(); // ------> here
dead lock happens.
Since the accessToResource and readMutex's permit is 1, neither the Reader nor the Writter could move forward.

Using CountDownLatch & Object.wait inside recursive block hangs

Problem: While trying to retrieve values inside a recursive block in a phased manner, the execution gets hung.
Description: CountDownLatch & Object.wait are used to achieve the phased manner access of value inside the recursive block. But, the program hangs with following output:
2 < 16
3 < 16
4 < 16
5 < 16
Current total: 5
Inside of wait
Inside of wait
Program:
import java.util.concurrent.*;
public class RecursiveTotalFinder {
private static CountDownLatch latch1;
private static CountDownLatch latch2;
private static CountDownLatch latch3;
public static void main(String... args) {
latch1 = new CountDownLatch(1);
latch2 = new CountDownLatch(1);
latch3 = new CountDownLatch(1);
//Create object
TotalFinder tf = new TotalFinder(latch1,latch2,latch3);
//Start the thread
tf.start();
//Wait for results from TotalFinder
try {
latch1.await();
} catch(InterruptedException ie) {
ie.printStackTrace();
}
//Print the result after 5th iteration
System.out.println("Current total: "+tf.getCurrentTotal());
tf.releaseWaitLock();
tf.resetWaitLock();
//Wait for results again
try {
latch2.await();
} catch(InterruptedException ie) {
ie.printStackTrace();
}
//Print the result after 10th iteration
System.out.println("Current total: "+tf.getCurrentTotal());
tf.releaseWaitLock();
tf.resetWaitLock();
//Wait for results again
try {
latch3.await();
} catch(InterruptedException ie) {
ie.printStackTrace();
}
//Print the result after 15th iteration
System.out.println("Current total: "+tf.getCurrentTotal());
tf.releaseWaitLock();
tf.resetWaitLock();
}
}
class TotalFinder extends Thread{
CountDownLatch tfLatch1;
CountDownLatch tfLatch2;
CountDownLatch tfLatch3;
private static int count = 1;
private static final class Lock { }
private final Object lock = new Lock();
private boolean gotSignalFromMaster = false;
public TotalFinder(CountDownLatch latch1, CountDownLatch latch2,
CountDownLatch latch3) {
tfLatch1 = latch1;
tfLatch2 = latch2;
tfLatch3 = latch3;
}
public void run() {
findTotal(16);
}
//Find total
synchronized void findTotal(int cnt) {
if(count%5==0) {
if(count==5)
tfLatch1.countDown();
if(count==10)
tfLatch2.countDown();
if(count==15)
tfLatch3.countDown();
//Sleep for sometime
try {
Thread.sleep(3000);
} catch(InterruptedException ie) {
ie.printStackTrace();
}
//Wait till current total is printed
synchronized(lock) {
while(gotSignalFromMaster==false) {
try {
System.out.println(" Inside of wait");
lock.wait();
} catch(InterruptedException ie) {
ie.printStackTrace();
}
}
System.out.println("Came outside of wait");
}
}
count +=1;
if(count < cnt) {
System.out.println(count +" < "+cnt);
findTotal(cnt);
}
}
//Return the count value
public int getCurrentTotal() {
return count;
}
//Release lock
public void releaseWaitLock() {
//Sleep for sometime
try {
Thread.sleep(5000);
} catch(InterruptedException ie) {
ie.printStackTrace();
}
synchronized(lock) {
gotSignalFromMaster=true;
lock.notifyAll();
}
}
//Reset wait lock
public void resetWaitLock() {
gotSignalFromMaster = false;
}
}
Analysis:
In my initial analysis it looks like the wait is happening recursively eventhough notifyAll is invoked from the main program.
Help:
Why free lock using notfiyAll after a CountDownLatch didn't take effect? Need someone's help in understanding what exactly is happening in this program.
The main message about wait and notify that I got from JCIP was that I'd probably use them wrongly, so better to avoid using them directly unless strictly necessary. As such, I think that you should reconsider the use of these methods.
In this case, I think that you can do it more elegantly using SynchronousQueue. Perhaps something like this might work:
import java.util.concurrent.*;
public class RecursiveTotalFinder {
public static void main(String... args) throws InterruptedException {
SynchronousQueue<Integer> syncQueue = new SynchronousQueue<>();
//Create object
TotalFinder tf = new TotalFinder(syncQueue, 5);
//Start the thread
tf.start();
for (int i = 0; i < 3; ++i) {
System.out.println("Current total: " + syncQueue.take());
}
}
}
class TotalFinder extends Thread{
private final SynchronousQueue<Integer> syncQueue;
private final int syncEvery;
private int count;
public TotalFinder(SynchronousQueue<Integer> syncQueue,
int syncEvery) {
this.syncQueue = syncQueue;
this.syncEvery = syncEvery;
}
public void run() {
try {
findTotal(16);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
}
//Find total
void findTotal(int cnt) throws InterruptedException {
if((count > 0) && (count%syncEvery==0)) {
syncQueue.put(count);
}
count +=1;
if(count < cnt) {
System.out.println(count +" < "+cnt);
findTotal(cnt);
}
}
}
As to why your original approach doesn't work, it's because the main thread sets gotSignalFromMaster to true and then immediately back to false, and this happens before the other thread is able to check its value. If you stick a bit of a sleep into the resetWaitLock, it proceeds beyond the point where it currently hangs; however, it then hangs at the end instead of terminating.
Note that having to use Thread.sleep to wait for another thread to change some state is a poor approach - not least because it makes your program really slow. Using synchronization utilities leads to faster and much easier-to-reason-about program.

producer - consumer multithreading in Java

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.

Categories