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

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.

Related

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

Java: Thread on Event every specific time interval (Issue Observer inside Thread: EventSource.run() method runs in an infinite loop)

I'm doing a thread who tells me when an event happens. I think that thread is not necessary if event can be controlled by timer for example. But I need an event every minute. Trouble are two:
1. When event is inside a thread occurs too fast. It seems like loop over thread. But threads are necessary to listen or catch an event.
2. I can't tell method which custom object must dispatch event, and then capture this event from a new class
I hope that you can help, here is code:
import java.util.Observer;
import java.util.Observable;
public class Main {
public static void main(String[] args) {
Threading test = new Threading();
test.start();
}
}
class ResponseHandler implements Observer {
#Override
public void update(Observable obj, Object arg) {
if (arg instanceof String) {
String resp = (String) arg;
System.out.println("\n Received response: " + resp);
}
}
}
class EventSource extends Observable implements Runnable {
#Override
public void run() {
try {
while (true) {
Object msg = new Object(); //I guess that this must have an object here, that throws a timeout
setChanged();
notifyObservers(msg);
}
} catch (Exception e) { e.printStackTrace();}
}
}
class Obj {
EventSource _eventSource;
ResponseHandler _responseHandler;
public Obj() {
try {
_eventSource = new EventSource();
_responseHandler = new ResponseHandler();
_eventSource.addObserver(_responseHandler);
} catch (Exception ex) {
System.out.print(ex);
}
}
}
class Threading extends Obj implements Runnable {
Thread _thread;
public void run() {
while (true) {
try {
_eventSource.run(); //Event which never stops
Thread.sleep(1000); //hey thread what are you doing?
} catch (InterruptedException ex) {
}
System.out.println("Thread");
}
}
//Singlethon
public void start() {
if (_thread == null) {
_thread = new Thread(this);
_thread.start();
}
}
}

BlockingQueue: how can multiple producers stop a single consumer?

I wrote a producer/consumer based program using Java's BlockingQueue. I'm trying to find a way to stop the consumer if all producers are done. There are multiple producers, but only one consumer.
I found several solutions for the "one producer, many consumers" scenario, e.g. using a "done paket / poison pill" (see this discussion), but my scenario is just the opposite.
Are there any best practice solutions?
The best-practice system is to use a count-down latch. Whether this works for you is more interesting.....
Perhaps each producer should register and deregister with the consumer, and when all producers are deregistered (and the queue is empty) then the consumer can terminate too.
Presumably your producers are working in different threads in the same VM, and that they exit when done. I would make another thread that calls join() on all the producers in a loop, and when it exist that loop (because all the producer threads have ended) it then notifies the consumer that it's time to exit. This has to run in another thread because the join() calls will block. Incidentally, rolfl's suggestion of using a count down latch would have the problem, if I understand it correctly.
Alternately, if the producers are Callables, then the consumer can call isDone() and isCanceled() on their Futures in the loop, which won't bock, so it can be used right in the consumer thread.
You could use something like the following, i use registerProducer() and unregisterProducer() for keeping track of the producers. Another possible solution could make use of WeakReferences.
It's worth to mention that this solution will not consume the events that have already been queued when the consumer is shut down, so some events may be lost when shutting down.
You would have to drain the queue if the consumer gets interrupt and then process them.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public class TestConsumerShutdown {
private static interface SomeEvent {
String getName();
}
private static class Consumer implements Runnable {
private final BlockingQueue<SomeEvent> queue = new ArrayBlockingQueue<>(10);
private final ExecutorService consumerExecutor = Executors.newSingleThreadExecutor();
private final AtomicBoolean isRunning = new AtomicBoolean();
private final AtomicInteger numberProducers = new AtomicInteger(0);
public void startConsumer() {
consumerExecutor.execute(this);
}
public void stopConsumer() {
consumerExecutor.shutdownNow();
try {
consumerExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
public void registerProducer() {
numberProducers.incrementAndGet();
}
public void unregisterProducer() {
if (numberProducers.decrementAndGet() < 1) {
stopConsumer();
}
}
public void produceEvent(SomeEvent event) throws InterruptedException {
queue.put(event);
}
#Override
public void run() {
if (isRunning.compareAndSet(false, true)) {
try {
while (!Thread.currentThread().isInterrupted()) {
SomeEvent event = queue.take();
System.out.println(event.getName());
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
System.out.println("Consumer stopped.");
isRunning.set(false);
}
}
}
}
public static void main(String[] args) {
final Consumer consumer = new Consumer();
consumer.startConsumer();
final Runnable producerRunnable = new Runnable() {
#Override
public void run() {
final String name = Thread.currentThread().getName();
consumer.registerProducer();
try {
for (int i = 0; i < 10; i++) {
consumer.produceEvent(new SomeEvent() {
#Override
public String getName() {
return name;
}
});
}
System.out.println("Produver " + name + " stopped.");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
consumer.unregisterProducer();
}
}
};
List<Thread> producers = new ArrayList<>();
producers.add(new Thread(producerRunnable, "producer-1"));
producers.add(new Thread(producerRunnable, "producer-2"));
producers.add(new Thread(producerRunnable, "producer-3"));
for (Thread t : producers) {
t.start();
}
}
}

Create a new Event Handler and Source

I have a User Interface(UI) class. It creates some thread (lets call it T) to do some work. I want my UI class to be notified when T is done working.
I think I need to create an event handler in UI class (among onClick() etc) and trigger it from T.
Question: Is this possible ? How ?
//to be clear, UI class does already have some event Handlers which are triggered by functions I didn't write. like onClick() , etc.
This is a fairly common requirement as you generally want to be doing as little as possible on the UI thread.
If you are using swing, have a look at the SwingWorker class. If you are not using swing, you might want to have a look at ExecutorService and FutureTask.
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
public class Futures {
public static void main(String[] args) {
UI ui = new UI();
FutureHandle<String> handle = new FutureHandle<String>(new BigJob());
FutureHandle<String> handle2 = new FutureHandle<String>(new BigJob());
ui.doUIStuff("Things can happen on the UI thread");
ui.startHeavyLiftingJob(handle);
ui.doUIStuff("I've got a big job running, but I'm still responsive");
ui.startHeavyLiftingJob(handle2);
}
/**
* Your UI class. Don't want to do anything big
* on the UI's thread.
*/
static class UI implements Listener<String> {
private ExecutorService threadPool = Executors.newFixedThreadPool(5);
public void doUIStuff(String msg) {
System.out.println(msg);
}
public void startHeavyLiftingJob(FutureHandle<String> handle) {
System.out.println("Starting background task");
handle.setListener(this);
threadPool.execute(handle);
}
public void callback(String result) {
System.out.println("Ooh, result ready: " + result);
}
}
/**
* A handle on a future which makes a callback to a listener
* when the callable task is done.
*/
static class FutureHandle<V> extends FutureTask<V> {
private Listener<V> listener;
public FutureHandle(Callable<V> callable) {
super(callable);
}
#Override
protected void done() {
try {
listener.callback(get());
} catch (InterruptedException e) {
//handle execution getting interrupted
} catch (ExecutionException e) {
//handle error in execution
}
}
public void setListener(Listener<V> listener) {
this.listener = listener;
}
}
/**
* Class that represents something you don't want to do on the UI thread.
*/
static class BigJob implements Callable<String> {
public String call() throws Exception {
Thread.sleep(2000);
return "big job has finished";
}
}
interface Listener<V> {
public void callback(V result);
}
}

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