Implementing a Semaphore with a Queue - java

I am trying to create a basic Semaphore implementation using Queue. The idea is, there is a database, and there are 10 writers. Writers can only write to the database in mutual exclusion. I am using Queue because I want to implement First In First Out and Last In First Out.
Using Semaphore, I can't notify a specific thread to wake up. So my idea is what I am doing is for every Writer, I create an object and tell the Writer to wait on that object. Puts that object in a queue. Then remove the object from the queue and notify the Thread that is waiting on that object. In this way, I think I can make a FIFO or LIFO implementation.
I need help on the actual code implementation:
1. I run the code below, it gave me a lot of IllegalMonitorStateException.
2. FIFO and LIFO code (my FIFO code seems incorrect, while for LIFO code, I'm thinking to use Stack instead of Queue).
public class Test {
public static void main(String [] args) {
Database db = new Database();
for (int i = 0; i < 10; i++)
(new Thread(new Writer(db))).start();
}
}
public class Writer implements Runnable {
private Database database;
public Writer(Database database) {
this.database = database;
}
public void run() {
this.database.acquireWriteLock();
this.database.write();
this.database.releaseWriteLock();
}
}
public class Database {
private Semaphore lockQueue;
public Database() {
this.lockQueue = new Semaphore();
}
public void write() {
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {}
}
public void acquireWriteLock() {
lockQueue.acquire();
}
public void releaseWriteLock() {
lockQueue.release();
}
}
import java.util.Queue;
import java.util.LinkedList;
public class Semaphore {
private Queue<Object> queue;
public Semaphore() {
this.queue = new LinkedList<Object>();
}
public synchronized void acquire() {
Object object = new Object();
try {
if (this.queue.size() > 0) {
object.wait();
this.queue.add(object);
}
} catch (InterruptedException ie) {}
this.queue.add(object);
}
public synchronized void release() {
Object object = this.queue.remove();
object.notify();
}
}

You need to acquire the lock of the object before you can use wait() and notify().
Try to check if the following code will work:
public class Semaphore {
private Queue<Object> queue;
private int state;
public Semaphore() {
this.queue = new LinkedList<Object>();
}
public void acquire() {
Object object = new Object();
synchronized (object) {
try {
if (this.state > 0) {
this.queue.add(object);
object.wait();
} else {
state++;
}
} catch (InterruptedException ie) {
}
}
}
public void release() {
Object object = this.queue.poll();
state--;
if(null == object) {
return;
}
synchronized (object) {
object.notify();
}
}
}

Related

Adding and removing element from list concurrently

I want to create two threads that one adds elements into ArrayList (or vector) and the other removes elements from this list concurrently. For example, if thread1 adds 20 elements into the list, then thread2 starts removing at the same time until total elements are removed, but these two threads must be work at the same time.
I wrote a producer (adding to the list) thread. In this thread, when the number of elements added to the list is greater than 5 or any number, so new thread must be started but in here I am stuck. I will mark the point that I was stuck.
public class Test{
public static void main(String[] args) {
Data d = new Data();
Thread t = new Thread(new producer(d));
t.start();
}
}
class producer implements Runnable{
Data d;
Data d2;
Object lck;
public producer(Data dd)
{
d=dd;
}
#Override
public void run()
{
for (int i=0;i<100;++i ) {
synchronized (d){
d.a.add(i);
// if i is greater than 5,
// start consumer thread
// which remove elements from ArrayList.
// but how ??
Thread t = new Thread(new Runnable(){
#Override
public void run()
{
//if(d.a.isEmpty())
//wait the adder thread
}
});
t.start();
}
}
}
}
class Data{
ArrayList<Integer> a; // or vector
public Data()
{
a = new ArrayList<>();
}
}
How can I implement a remover thread that removes all elements in the list with the same time with adder thread and synchronize them?
You can try concurrent package of java .
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CopyOnWriteArrayList.html
You are using synchronized block in thread which will not help in this case. Method in collection or shared data should be synchronized as it will be accessed by multiple thread
In your code, you are creating 100 consumer thread in producer class within synchronized block. This is not efficient way to utilize parallelism using multi-threading. You are creating one thread for one data to be consumed. Once the data is consumed your thread will be in DEAD state and will not be useful to consume other incoming data, this is wastage of resource as well as requires more time to solve problem.
Take reference of below code to solve your consumer producer problem.
import java.util.*;
class Data {
final List<Integer> a;
public Data() {
a = new ArrayList<>();
}
}
public class Producer implements Runnable {
private final Data data;
public Producer(Data data) {
this.data = data;
}
#Override
public void run() {
for (int i = 0; i < 100; i++) {
synchronized (data) {
data.a.add(i);
}
}
}
}
public class Consumer implements Runnable {
private Data data;
private boolean isThreadEnabled = true;
public Consumer(Data data) {
this.data = data;
}
#Override
public void run() {
while (isThreadEnabled) {
synchronized (data) {
if (!data.a.isEmpty()) {
System.out.println(data.a.remove(0));
}
}
}
}
public void stopConsumer() {
isThreadEnabled = false;
}
}
public class ThreadsMain {
public static void main(String args[]) {
try {
Data data = new Data();
Consumer consumerRunnable = new Consumer(data);
Thread producer = new Thread(new Producer(data));
Thread consumer = new Thread(consumerRunnable);
producer.start();
consumer.start();
producer.join();
try {
//wait for consumer to consume data and then stop the thread
Thread.sleep(1000);
consumerRunnable.stopConsumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

Using Locks and Condition to simulate print server

I want to have print server that outputs the requested messages to the computer screen as follows: Client threads invoke the printRequestV1 method to submit the messages (strings) to be output. But all the printRequestV1 method should do is place the message in the print job queue, and a separate (manager) thread then dequeues messages from the job queue and outputs them to the screen
I know that I need to synchronize the shared request queue and check whether the queue is not empty before trying to remove a message. If the queue is empty, the manager thread needs to wait until client threads add some messages, and the client thread, after adding a message, will let the manager thread know by signaling.
Here what I have so far:
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
import static java.lang.System.out;
public class PrintServerV1 implements Runnable {
private static final Queue<String> requests = new LinkedList<String>();
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public PrintServerV1() {
try{
while(requests.size() != 0){ condition.await();}
new Thread(this).start();
}
catch (InterruptedException exception) {}
}
public void printRequest(String s) {
lock.lock();
try
{
out.println("Adding print request for: " +s);
requests.add(s);
condition.signalAll();
}
finally { lock.unlock(); }
}
public void sendRequest() throws InterruptedException
{
try {
while(requests.size() != 0){ condition.await();}
out.println("Sending Request to printer");
for(;;) realPrint(requests.remove());
} finally { lock.unlock(); }
}
private void realPrint(String s) {
// do the real work of outputting the string to the screen
out.println("Currently printing: " + s);
}
public void run(){
try{
sendRequest();
} catch (InterruptedException exception) {}
}
public static void main(String[] args){
PrintServerV1 server = new PrintServerV1();
server.printRequest("homework7.txt");
}
}
I am getting the following output:
Adding print request for: homework7.txt
Sending Request to printer
Currently printing: homework7.txt
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
at PrintServerV1.sendRequest(PrintServerV1.java:43)
at PrintServerV1.run(PrintServerV1.java:54)
at java.lang.Thread.run(Thread.java:748)
My question is wouldn't it better if make two classes, one named manager who implements runnable and whose sole purpose is to remove from the queue and one class named client who implements runnable and whose purpose is to add requests to the queue?
You can only unlock after you aquire the lock by lock, otherwise IllegalMonitorStateException will be thrown. You should also call await method after you aquiring the lock.
It is a bad idea to await in the construtor, it will cause the creation of instance get blocked;
Remove the elements only when the requests is not empty.
This code works fine on my machine:
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
import static java.lang.System.out;
public class PrintServerV1 implements Runnable {
private static final Queue<String> requests = new LinkedList<String>();
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void printRequest(String s) {
lock.lock();
try {
out.println("Adding print request for: " + s);
requests.add(s);
condition.signalAll();
} finally {
lock.unlock();
}
}
public void sendRequest() throws InterruptedException {
lock.lock();
try {
while (requests.size() == 0) {
condition.await();
}
out.println("Sending Request to printer");
while (!requests.isEmpty()) {
realPrint(requests.remove());
}
} finally {
lock.unlock();
}
}
private void realPrint(String s) {
// do the real work of outputting the string to the screen
out.println("Currently printing: " + s);
}
public void run() {
try {
sendRequest();
} catch (InterruptedException exception) {
}
}
public static void main(String[] args) {
PrintServerV1 server = new PrintServerV1();
new Thread(server).start();
server.printRequest("homework7.txt");
}
}
Output:
Adding print request for: homework7.txt
Sending Request to printer
Currently printing: homework7.txt
I suggest to use two threads, one producer and one consumer, as well as a BlockingQueue to solve this kind of problem. The synchronization will be handled by the blocking queue, so you can focus on you business logic.
import java.util.concurrent.LinkedBlockingQueue;
public class Main {
public static void main(String[] args) {
LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>();
new Thread(new Producer(queue)).start();
new Thread(new Consumer(queue)).start();
}
}
class Consumer implements Runnable {
private LinkedBlockingQueue<String> queue;
public Consumer(LinkedBlockingQueue<String> queue) {
this.queue = queue;
}
#Override
public void run() {
while (true) {
String request;
try {
request = queue.take();
System.out.println(request);
} catch (Exception e) {
}
}
}
}
class Producer implements Runnable {
private LinkedBlockingQueue<String> queue;
public Producer(LinkedBlockingQueue<String> queue) {
this.queue = queue;
}
#Override
public void run() {
try {
queue.put("homework7.txt");
} catch (Exception e) {
}
}
}

Why doesn't my consumer consume Integer values? (Producer-Consumer with wait and notify)

I have two threads. One is a producer (class Deliver), second is consumer (class Produce). I want to simulate door producer. So producer deliver wood that consumer can produce a door. But i do not real get how to communicate between those two threads. Now when i run my program only wood is delivered but doors are not produced. I do not get why.
public class Deliver implements Runnable {
private static int MAX_STOCKPILE = 15;
private Integer wood;
public Deliver(Integer wood) {
this.wood = wood;
new Thread(this, "Deliver").start();
}
public synchronized void deliver() throws InterruptedException{
Thread.sleep(500);
if (wood < MAX_STOCKPILE) {
wood++;
System.out.println("Wood delivered" + " | Wood stockpile: " + wood);
notify();
}
else {
wait();
}
}
#Override
public void run() {
while (true) {
try {
deliver();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Produce implements Runnable{
private Integer wood;
public Produce(Integer wood) {
this.wood = wood;
new Thread(this, "Produce").start();
}
public synchronized void produce() throws InterruptedException{
Thread.sleep(1000);
if (wood == 10) {
wood -= 10; //produce
System.out.println("Doors produced");
notify();
}
else {
wait();
}
}
#Override
public void run() {
while (true) {
try {
produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Main {
public static void main(String[] args) {
Integer wood = 0;
new Deliver(wood);
new Produce(wood);
}
}
Now when i run my program only wood is delivered but doors are not produced. I do not get why
There are multiple issues with your code :
When you mark an instance method as synchronized, any thread entering that method will obtain a lock on this (i.e the instance on which the method was called). Since this in Deliver refers to a Deliver instance and this in Produce refers to a Produce instance, the wait and notify calls are practically useless in this case as they are not interested in the same objects.
The golden rule to remember in Java is that it uses pass-by-value semantics. Primitives and references are therefore always passed by value. While you may assume that both Deliver and Produce will be modifying the same Integer passed to them from main, that is not the case.
That said, I would highly recommend that you consider using something like an ArrayBlockingQueue for solving this instead of reinventing the wheel with wait and notify.
Change
if (wood == 10) {
to
if (wood >= 10) {
in case the thread doesn't catch it when it == 10
Something to note is that Integer is immutable.
When you change the reference to the Integer you are creating a new object which has no relationship to the previous object.
What you want this an object which is shared between the two threads so when you change the value (but not the reference) they are looking at the same value.
e.g.
wood -= 10;
is the same as
wood = Integer.valueOf(wood.intValue() - 10);
I suggest using AtomicInteger and making the reference to it final to ensure you don't accidentally try to change the reference.
As Andrew Jenkins suggests; if you lock, notify/wait on unrelated objects, you don't have any thread safety. Once you have a shared object, you have to lock, notify/wait on that shared object.
I'll throw my solution into the mix, taking into account Peter Lawrey's advice about using AtomicInteger.
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
public static void main(String[] args) {
AtomicInteger wood = new AtomicInteger(0);
new Deliver(wood);
new Produce(wood);
}
}
public class Deliver implements Runnable {
private static int MAX_STOCKPILE = 15;
private final AtomicInteger wood;
public Deliver(AtomicInteger wood) {
this.wood = wood;
new Thread(this, "Deliver").start();
}
public void deliver() throws InterruptedException{
Thread.sleep(500);
synchronized(wood) {
if (wood.intValue() < MAX_STOCKPILE) {
wood.addAndGet(1);
System.out.println("Wood delivered" + " | Wood stockpile: " + wood);
wood.notify();
} else {
wood.wait();
}
}
}
#Override
public void run() {
while (true) {
try {
deliver();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Produce implements Runnable{
private final AtomicInteger wood;
public Produce(AtomicInteger wood) {
this.wood = wood;
new Thread(this, "Produce").start();
}
public void produce() throws InterruptedException{
synchronized(wood) {
if (wood.intValue() >= 10) {
wood.addAndGet(-10); //produce
System.out.println("Doors produced");
wood.notify();
}
else {
wood.wait();
}
}
}
#Override
public void run() {
while (true) {
try {
produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Key changes:
We use a mutable object to communicate between threads (AtomicInteger).
We synchronize on the mutable object, not the thread being run.

Exception in thread "Thread-0" java.util.NoSuchElementException?

I am new to using threads. In another class an instance of the ConnectionMaster class is created and started (extends thread). A Client object is given to the ConnectionMaster object which adds it to the list. The overridden run() method of the Thread class essentially listens for a client to be added to the list. Indeed it does listen and "hears" when a Client object is added to the list. However, although .hasNext() returns true .Next() causes an exception. What am I doing wrong?
The following methods are from class ConnectionMaster which extends Thread:
Constructor
public ConnectionMaster(){
clients = new Vector<>();
listIterator = clients.listIterator();
}
Public method for adding client objects to the list
#Override
public synchronized void addClient(Client client) {
listIterator.add(client);
}
This is the overridden thread method of the class Thread. It consistently checks for elements added to the list.
#Override
public void run(){
while(true){
while(listIterator.hasNext()){
processClient(listIterator.next()); //this is where error occurs
listIterator.remove();
}
while(listIterator.hasPrevious()){
processClient(listIterator.previous());
listIterator.remove();
}
}
}
////////////////////////////////UPDATE////////////////////////////////////
Thank You OldCurmudgeon and Stephen C.
Based on your feedback, my code has been modified thus:
Constructor
public ConnectionMaster(){
clients = new ArrayBlockingQueue<Client>(1024);
}
Method for receiving client objects
#Override
public synchronized void addClient(Client client) {
try {
clients.put(client);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Listener
#Override
public void run(){
while(true){
try {
processClient((Client)clients.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
This is a very strange way to implement Producer/Consumer. The usual way is to use a BlockingQueue.
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) {
try {
Integer i = queue.take();
ended = i == End;
System.out.println(i);
} catch (InterruptedException ex) {
ended = true;
}
}
}
}
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();
}
}
What am I doing wrong?
Quite a lot actually.
First thing you are doing wrong is (apparently) using an ListIterator object in multiple threads. The ListIterator and Iterator implementations for Vector are not thread-safe1, so what you are doing is potentially hazardous.
The second thing is that even if the iterators / list iterators were thread-safe, you are performing a sequence of operations (e.g. hasNext, next, remove) without doing anything to ensure that the sequence of operations is performed in a way that is threadsafe. There is a distinct possibility that two threads could be performing the same sequence simultaneously on the shared iterator, and that one could interfere with the other.
I'm not sure what to suggest in order to fix your code. Two threads sharing an iterator is not going to work.
It would probably be better to ditch it, and use some kind of Queue as suggested by #OldCurmugeon.
Either problem 1 or problem 2 (as outlined above) could give rise to NoSuchElement exceptions.
1 - This is apparent from examining the source code - http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/Vector.java#Vector.ListItr .

How to watch my Thread variable from Main class?

I have that code:
Main class:
public class myTest {
public static void main(String[] args) {
try {
Thread t1 = new myThreadClass("thread 1");
t1.start();
} catch (UnknownHostException ex) {
Logger.getLogger(glownyTest.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(glownyTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
My Thread class
public class myThreadClass extends Thread {
private HashSet<String> texts = new HashSet<String>();
public myThreadClass(String id) throws UnknownHostException, IOException {}
#Override
public void run() {
... collecting Strings into my hashSet ....
}
public HashSet<String> getTexts() {
return texts;
}
}
My Thread class is watching for network traffic, so I just cant call once
t1.getTexts()
whenever I want, because my hashSet can be empty (there are delays and latency in this network). How can I watch this texts hashSet and when some String will be added into hashSet - I i want my MAIN CLASS know about it? I just want to watch my Thread resources from Main class in smart way :)
If it will still be empty after my thread timeout, I want to know about it too.
You can use condition variables for this. Try something like:
class Monitor {
private final ConcurrentMap<String,String> data = new ConcurrentHashMap<String,String>();
private final Object mutex = new Object();
/* Private to the monitoring thread. Wakes up other
* threads, which may be waiting for data to arrive
*/
public void addElement(String key) {
data.put(key, key);
synchronized (mutex) { mutex.notifyAll(); }
}
public void removeElement(String key) {
data.remove(key);
synchronized (mutex) { mutex.notifyAll(); }
}
public Set<String> getElements() {
return data.keySet();
}
/* Can be called from any thread. Will wait at most "timeout"
* milliseconds
*/
public boolean waitForChanges(long timeout) throws InterruptedException {
final long then = System.currentTimeMillis() + timeout;
long left = timeout;
synchronized (mutex) {
while (data.isEmpty() && left > 0) {
mutex.wait(left);
left = then - System.currentTimeMillis();
}
return !data.isEmpty();
}
}
}
class MonitoringTask extends Runnable {
private final Monitor monitor;
MonitoringTask(Monitor m) {
this.monitor = m;
}
public void run() {
while (true) {
if (somethingHasHappened()) {
monitor.addElement("foo");
}
}
}
}
class Main {
public static void main(String[] args) {
final Monitor monitor = new Monitor();
final MonitoringTask task = new MonitoringTask(monitor);
final Thread thread = new Thread(task);
thread.setName("Monitor Thread");
thread.start();
if (monitor.waitForChanges(1500)) {
final Set<String> elts = monitor.getElements();
...
} else {
// Time-out
}
}
}
(I haven't tried to present this to a Java compiler, so watch out for all kinds of mistakes).

Categories