Using Locks and Condition to simulate print server - java

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) {
}
}
}

Related

Java lock's condition implementation

Need help with code at below link as it should run indefinitely likewise with any typical producer/consumer problem but somehow it is getting stuck on call of condition.signal(). What am I doing wrong here?
In main method, I have created two thread, one is consumer and other one is producer. it has shared task queue where both updates the entry.
package com.anurgup.handson;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ConditionService implements Runnable {
Lock lock = new ReentrantLock();
Condition added = lock.newCondition();
Condition removed = lock.newCondition();
// type of service
String type;
// shared task for insertion and deletion of task
static Queue<Integer> task = new PriorityQueue<Integer>();
// max number of task allowed
private static final int MAX_SIZE = 5;
public ConditionService(String type) {
this.type = type;
}
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(2);
service.submit(new ConditionService("producer"));
service.submit(new ConditionService("consumer"));
}
public void produce() {
try {
while (true) {
System.out.println("in producer...");
synchronized (task) {
while (task.size() == MAX_SIZE)
removed.await();
System.out.println("added item: " + task.size());
task.add(task.size());
added.signal();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void consume() {
try {
while (true) {
System.out.println("in consumer...");
synchronized (task) {
while (task.isEmpty())
added.await();
System.out.println("removed item: " + task.peek());
task.remove();
removed.signal();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void run() {
if (this.type.equals("producer"))
this.produce();
else
this.consume();
}
}
You're making two mistakes. First, your lock and conditions need to be static, or each task will only synchronize and wait on itself. Second, you need to use lock.lock(), not synchronized. It should look like this:
lock.lock();
try {
// wait
// produce/consume
} finally {
lock.unlock();
}

Calling Thread.Sleep in Subscriber thread causes Publisher thread to sleep

I have implemented Publish and Subscribe pattern in my application but when I called Thread.sleep() method in any one Subscriber or any one of my Subscriber throws exception then all others subscribers and publishers gets affected by this so how can I prevent this from happening.
I have created one small demo of above problem
Publisher Code
import java.util.Random;
public class Publisher extends Thread {
Broker broker = Broker.getInstance();
Random random = new Random();
#Override
public void run() {
while (true) {
System.out.println("Published " + new Timestamp(System.currentTimeMillis()));
broker.updateSubscribers(Integer.toString(random.nextInt(250)));
}
}
}
Subscriber Interface
public interface Subscriber {
public void onUpdate(String message);
}
MessageSubscriber code
import java.util.logging.Level;
import java.util.logging.Logger;
public class MessageSubscriber extends Thread implements Subscriber {
Broker broker = Broker.getInstance();
#Override
public void run() {
System.out.println("MessageSubscriber started...");
broker.subscribe(this);
}
#Override
public void onUpdate(String message) {
try {
System.out.println(message);
sleep(1000); // called sleep affects the publisher too
} catch (InterruptedException ex) {
Logger.getLogger(MessageSubscriber.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
As you can see I have called sleep method in MessageSubscriber which also affects the Publisher and makes it sleep too for that duration
Edit added Broker Code
import java.util.ArrayList;
import java.util.List;
/**
*
* #author hemants
*/
public class Broker {
List<Subscriber> subscribersList = new ArrayList<>();
private Broker() {
}
public static Broker getInstance() {
return BrokerHolder.INSTANCE;
}
private static class BrokerHolder {
private static final Broker INSTANCE = new Broker();
}
public void subscribe(Subscriber s) {
subscribersList.add(s);
}
public void unsubscribe(Subscriber s) {
subscribersList.remove(s);
}
public void updateSubscribers(String message) {
subscribersList.stream().forEach(subscriber -> subscriber.onUpdate(message));
}
}
Main class to run above code
public class PubSubPattern {
public static void main(String[] args) {
Publisher publisher = new Publisher();
publisher.start();
MessageSubscriber messageSubscriber = new MessageSubscriber();
messageSubscriber.start();
}
}
Well I have edited my MessageSubscribe code like below and it is doing kind of what I have expected
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* #author hemants
*/
public class MessageSubscriber extends Thread implements Subscriber {
Broker broker = Broker.getInstance();
#Override
public void run() {
System.out.println("MessageSubscriber started...");
while (true) {
try {
broker.subscribe(this);
System.out.println("subscribed ");
sleep(1000);
broker.unsubscribe(this);
System.out.println("un subscribed");
sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(MessageSubscriber.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
#Override
public void onUpdate(String message) {
System.out.println(message);
}
}
What do you say about this
So you execute sometyhing like this
subscribersList.stream().forEach(subscriber -> subscriber.onUpdate(message));
and during onUpdate you sleep
so its effectively
subscribersList.stream().forEach(subscriber -> Thread.sleep());
or even more verbose
for(Subscriber sub:subscribers){
Thread.sleep(xxx);
}
No wonder it "affects" other listener as caller is blocked here. Caller thread sleeps on every element.
Either use thread pool and submit update tasks, or use subscribersList.parallelStream()
I hope this is only for educational purposes.
You are updating the subscriber in same thread that is why it will affect the other subscriber. And also block the Publisher.
Create new Thread to update the broker and it would be fine.
Here is a quick solution. I updated the MessageSubscriber to keep the usage of the interface Subscriber within the Broker:
public class MessageSubscriber extends Thread implements Subscriber {
Broker broker = Broker.getInstance();
#Override
public void run() {
System.out.println("MessageSubscriber started...");
synchronized (broker) {
broker.subscribe(this);
}
try {
synchronized (this) {
wait();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
// TODO OP has to decide how to handle this
// for example
synchronized (broker) {
broker.unsubscribe(this);
}
}
}
#Override
public void onUpdate(String message) {
try {
synchronized (this) {
notify();
}
System.out.println(message);
sleep(1000); // called sleep affects the publisher too
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
Logger.getLogger(MessageSubscriber.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
I'm not sure about the handling of the InterruptedException within run() as the lock for boker has to be aquired to enter the synchronized block. Thus it's possible that the thread will wait for this lock instead of interrupting itself effectively.

Implementing a Semaphore with a Queue

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();
}
}
}

Wait for recursive Thread-Producer

I have a gatherer, that searches for moves in a game. I search in a recursive search, to get every possible move from the game.
For performance cause, I use a Threadpool and every found move adds a new Thread to the pool, to maybe extend the old move.
Here is some code:
protected static List<Runnable> threads;
private static ExecutorService threadPool;
protected final synchronized void hookThread(Runnable thread) {
if (threadPool == null) {
threadPool = Executors.newFixedThreadPool(15);
threads = new ArrayList<Runnable>();
}
threadPool.execute(thread);
threads.add(thread);
}
protected abstract class GathererRunnable implements Runnable {
#Override
public final void run() {
onRun();
threads.remove(this);
}
public abstract void onRun();
}
This is a snippet of the parent class. Now comes the child, that searches for the moves.
private void extendMove(final byte[] stones, final ByteLayMove move) {
Runnable r = new GathererRunnable() {
#Override
public void onRun() {
// fancy search stuff
if (moveIsFound)
extendMove(...);
}
};
hookThread(r);
}
The problem is now, that I don't know how I should can wait for the threads to finish.
I tried to use a int, that counts up on Thread Creation and down on Thread Completion, but that also resultet in a too early search abortion.
Do you have an idea if there is a nice way to wait for these threads?
I already thought about a BlockingQueue, but I don't have any idea how to implement it properly.
Greeting Kevin
Below program has implemented producer consumer scenario using BlockingQueue , you can use such approach while writing your own implementation.
import java.util.concurrent.*;
public class ThreadingExample {
public static void main(String args[]){
BlockingQueue<Message> blockingQueue = new ArrayBlockingQueue<Message>(100);
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new Producer(blockingQueue));
exec.execute(new Consumer(blockingQueue));
}
}
class Message{
private static int count=0;
int messageId;
Message(){
this.messageId=count++;
System.out.print("message Id"+messageId+" Created ");
}
}
class Producer implements Runnable{
private BlockingQueue<Message> blockingQueue;
Producer(BlockingQueue<Message> blockingQueue){
this.blockingQueue=blockingQueue;
}
#Override
public void run(){
while(!Thread.interrupted()){
System.out.print("Producer Started");
try {
blockingQueue.put(new Message());
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Producer Done");
}
}
}
class Consumer implements Runnable{
private BlockingQueue<Message> blockingQueue;
Consumer(BlockingQueue<Message> blockingQueue){
this.blockingQueue=blockingQueue;
}
#Override
public void run(){
while(!Thread.interrupted()){
System.out.print("Concumer Started");
try{
Message message = blockingQueue.take();
System.out.print("message Id"+message.messageId+" Consumed ");
}
catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Concumer Done");
}
}
}

How to thread-safe signal threads to pause in Java

I have a bunch of threads running concurrently. Sometimes a thread needs to notify other threads to wait for it to finish a job and signal them again to resume. Since I'm somehow new to Java's synchronization, I wonder what is the right way to do such thing. My code is something like this:
private void Concurrent() {
if (shouldRun()) {
// notify threads to pause and wait for them
DoJob();
// resume threads
}
// Normal job...
}
Update:
Note that the code I wrote is inside a class which will be executed by each thread. I don't have access to those threads or how they are running. I'm just inside threads.
Update 2:
My code is from a crawler class. The crawler class (crawler4j) knows how to handle concurrency. The only thing I need is to pause other crawlers before running a function and resume them afterwards. This code is the basics of my crawler:
public class TestCrawler extends WebCrawler {
private SingleThread()
{
//When this function is running, no other crawler should do anything
}
#Override
public void visit(Page page) {
if(SomeCriteria())
{
//make all other crawlers stop until I finish
SingleThread();
//let them resume
}
//Normal Stuff
}
}
Here is a short example on how to achieve this with the cool java concurrency stuff:
snip old code doesn't matter anymore with the Pause class.
EDIT:
Here is the new Test class:
package de.hotware.test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
private Pause mPause;
public Test() {
this.mPause = new Pause();
}
public void concurrent() throws InterruptedException {
while(true) {
this.mPause.probe();
System.out.println("concurrent");
Thread.sleep(100);
}
}
public void crucial() throws InterruptedException {
int i = 0;
while (true) {
if (i++ % 2 == 0) {
this.mPause.pause(true);
System.out.println("crucial: exclusive execution");
this.mPause.pause(false);
} else {
System.out.println("crucial: normal execution");
Thread.sleep(1000);
}
}
}
public static void main(String[] args) {
final Test test = new Test();
Runnable run = new Runnable() {
#Override
public void run() {
try {
test.concurrent();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
Runnable cruc = new Runnable() {
#Override
public void run() {
try {
test.crucial();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
ExecutorService serv = Executors.newCachedThreadPool();
serv.execute(run);
serv.execute(run);
serv.execute(cruc);
}
}
And the utility Pause class:
package de.hotware.test;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Utility class to pause and unpause threads
* with Java Concurrency
* #author Martin Braun
*/
public class Pause {
private Lock mLock;
private Condition mCondition;
private AtomicBoolean mAwait;
public Pause() {
this.mLock = new ReentrantLock();
this.mCondition = this.mLock.newCondition();
this.mAwait = new AtomicBoolean(false);
}
/**
* waits until the threads until this.mAwait is set to true
* #throws InterruptedException
*/
public void probe() throws InterruptedException {
while(this.mAwait.get()) {
this.mLock.lock();
try {
this.mCondition.await();
} finally {
this.mLock.unlock();
}
}
}
/**
* pauses or unpauses
*/
public void pause(boolean pValue) {
if(!pValue){
this.mLock.lock();
try {
this.mCondition.signalAll();
} finally {
this.mLock.unlock();
}
}
this.mAwait.set(pValue);
}
}
The basic usage is to call probe() before each run. This will block if it is paused until pause(false) is called.
Your class would look like this:
public class TestCrawler extends WebCrawler {
private Pause mPause;
public TestCrawler(Pause pPause) {
this.mPause = pPause;
}
private SingleThread()
{
//When this function is running, no other crawler should do anything
}
#Override
public void visit(Page page) {
if(SomeCriteria())
{
//only enter the crucial part once if it has to be exclusive
this.mPause.probe();
//make all other crawlers stop until I finish
this.mPause.pause(true);
SingleThread();
//let them resume
this.mPause.pause(false);
}
this.mPause.probe();
//Normal Stuff
}
}
public class StockMonitor extends Thread {
private boolean suspend = false;
private volatile Thread thread;
public StockMonitor() {
thread = this;
}
// Use name with underscore, in order to avoid naming crashing with
// Thread's.
private synchronized void _wait() throws InterruptedException {
while (suspend) {
wait();
}
}
// Use name with underscore, in order to avoid naming crashing with
// Thread's.
public synchronized void _resume() {
suspend = false;
notify();
}
// Use name with underscore, in order to avoid naming crashing with
// Thread's.
public synchronized void _suspend() {
suspend = true;
}
public void _stop() {
thread = null;
// Wake up from sleep.
interrupt();
}
#Override
public void run() {
final Thread thisThread = Thread.currentThread();
while (thisThread == thread) {
_wait();
// Do whatever you want right here.
}
}
}
Calling _resume and _suspend will enable you to resume and pause the Thread. _stop will let you stop the thread gracefully. Note that, once you stop the Thread, there is no way to resume it again. The Thread is no longer usable.
The code is being picked from a real world open source project : http://jstock.hg.sourceforge.net/hgweb/jstock/jstock/file/b17c0fbfe37c/src/org/yccheok/jstock/engine/RealTimeStockMonitor.java#l247
You can use wait() and notify()
thread waiting:
// define mutex as field
Object mutex = new Object();
// later:
synchronized(mutex) {
wait();
}
notify the thread to continue
synchronized (mutex) {
notify();
}

Categories