How to notifyAll threads in a class in JAVA? - java

Can I make a static function that notifyAll threads that are waiting in any instance of this class?
(The logic behind here is that I have queues that have threads waiting in them because they are empty and I want to finish the run of the program when calling this function)
queue = new Vector<T>();
public synchronized T extract(){
while(queue.isEmpty())
try {
this.wait();
if(!active) {return null;}
}catch(InterruptedException e) {}
T t = queue.elementAt(0);
queue.remove(0);
return t;
}
This is the extract method.
when the queue is empty the threads go into waiting.
I want to make the boolean "active" to false and notifyAll.
Then I will make sure the threads will not call this method anymore

The logic behind here is that I have queues that have threads waiting in them because they are empty and I want to finish the run of the program when calling this function
IMO, a better solution to your problem would be to continue using per-instance locks, but submit a poison pill to each queue when it's time to shut all of them down.
final T poison_pill = new T(...);
public synchronized T extract(){
while(queue.isEmpty())
try {
this.wait();
}catch(InterruptedException e) {}
T t = queue.elementAt(0);
if (t == poison_pill) {
...My preference would be to raise an exception here, but...
return NULL; // ...this was in your original example.
}
else {
queue.remove(0);
return t;
}
}
If you really want to be able to notify() all of the different instances at the same time, then you'll have to make all of them wait() on the same global lock object.
final Object global_lock = new Object();
public T extract(){
synchronized(global_lock) {
while(queue.isEmpty())
try {
global_lock.wait();
if(!active) {return null;}
}catch(InterruptedException e) {}
T t = queue.elementAt(0);
queue.remove(0);
return t;
}
}
And then somewhere else:
synchronized(lock) {
...
global_lock.notifyAll();
}

Related

How to ensure that `methodB` is "blocked" if some threads are in `methodA` in Java?

Class clazz has two methods methodA() and methodB().
How to ensure that methodB is "blocked" if some threads are in methodA in Java (I am using Java 8)?
By "blocking methodB", I mean that "wait until no threads are in methodA()". (Thanks to #AndyTurner)
Note that the requirement above allows the following situations:
Multiple threads are simultaneously in methodA.
Multiple threads are in methodB while no threads are in methodA.
Threads in methodB does not prevent other threads from entering methodA.
My trial: I use StampedLock lock = new StampedLock.
In methodA, call long stamp = lock.readLock()
Create a new method unlockB and call lock.unlockRead(stamp) in it.
In methodB, call long stamp = lock.writeLock() and lock.unlockWrite(stamp).
However, this locking strategy disallows the second and the third situations above.
Edit: I realize that I have not clearly specified the requirements of the synchronization between methodA and methodB. The approach given by #JaroslawPawlak works for the current requirement (I accept it), but not for my original intention (maybe I should first clarify it and then post it in another thread).
I think this can do the trick:
private final Lock lock = new ReentrantLock();
private final Semaphore semaphore = new Semaphore(1);
private int threadsInA = 0;
public void methodA() {
lock.lock();
threadsInA++;
semaphore.tryAcquire();
lock.unlock();
// your code
lock.lock();
threadsInA--;
if (threadsInA == 0) {
semaphore.release();
}
lock.unlock();
}
public void methodB() throws InterruptedException {
semaphore.acquire();
semaphore.release();
// your code
}
Threads entering methodA increase the count and try to acquire a permit from semaphore (i.e. they take 1 permit if available, but if not available they just continue without a permit). When the last thread leaves methodA, the permit is returned. We cannot use AtomicInteger since changing the count and acquiring/releasing permit from semaphore must be atomic.
Threads entering methodB need to have a permit (and will wait for one if not available), but after they get it they return it immediately allowing others threads to enter methodB.
EDIT:
Another simpler version:
private final int MAX_THREADS = 1_000;
private final Semaphore semaphore = new Semaphore(MAX_THREADS);
public void methodA() throws InterruptedException {
semaphore.acquire();
// your code
semaphore.release();
}
public void methodB() throws InterruptedException {
semaphore.acquire(MAX_THREADS);
semaphore.release(MAX_THREADS);
// your code
}
Every thread in methodA holds a single permit which is released when the thread leaves methodA.
Threads entering methodB wait until all 1000 permits are available (i.e. no threads in methodA), but don't hold them, which allows other threads to enter both methods while methodB is still being executed.
You can't really prevent that methodA or methodB is called (while other threads are inside the other method) but you can implement thread intercommunication in such a way so that you can still achieve what you want.
class MutualEx {
boolean lock = false;
public synchronized void methodA() {
if (lock) {
try {
wait();
}catch (InterruptedException e) {
}
}
//do some processing
lock = true;
notifyAll();
}
public synchronized void methodB() {
if (!lock) {
try {
wait();
}catch (InterruptedException e) {
}
}
//do some processing
lock = false;
notifyAll();
}
}
Now, for this to work any Thread object you create should have a reference to the same instance of MutualEx object.
Why not using an kind of external orchestrator?
I mean another class that will be responsible to call the methodA or methodB when it allowed.
Multi-thread can still be handle via locking or maybe just with some AtomicBoolean(s).
Please find below a naive draft of how to do it.
public class MyOrchestrator {
#Autowired
private ClassWithMethods classWithMethods;
private AtomicBoolean aBoolean = = new AtomicBoolean(true);
public Object callTheDesiredMethodIfPossible(Method method, Object... params) {
if(aBoolean.compareAndSet(true, false)) {
return method.invoke(classWithMethods, params);
aBoolean.set(true);
}
if ("methodA".equals(method.getName())) {
return method.invoke(classWithMethods, params);
}
}
}
In very simple terms what you all need is ENTER methodB only if no thread inside methodA.
Simply you can have a global counter, first initialized to 0 to record the number of threads that are currently inside methodA(). You should have a lock/mutex assigned to protect the variable count.
Threads entering methodsA do count++.
Threads exiting methodA do count-- .
Threads that are entering methodB first should check whether count == 0.
methodA(){
mutex.lock();
count++;
mutex.signal();
//do stuff
mutex.lock();
count--;
mutex.signal();
}
methodB(){
mutex.lock();
if(count != 0){
mutex.signal();
return;
}
mutex.signal();
//do stuff
}
You would need an int to count threads in methodA, and ReentrantLock.Condition to signal all threads waiting in methodB once there are no threads in methodA:
AtomicInteger threadsInMethodA = new AtomicInteger(0);
Lock threadsForMethodBLock = new ReentrantLock();
Condition signalWaitingThreadsForMethodB = threadsForMethodBLock.newCondition();
public void methodA() {
threadsInMethodA.incrementAndGet();
//do stuff
if (threadsInMethodA.decrementAndGet() == 0) {
try {
threadsForMethodBLock.lock();
signalWaitingThreadsForMethodB.signalAll();
} finally {
threadsForMethodBLock.unlock();
}
}
}
public void methodB() {
try {
threadsForMethodBLock.lock();
while (!Thread.isInterrupted() && threadsInMethodA.get() != 0) {
try {
signalWaitingThreadsForMethodB.await();
} catch (InterruptedException e) {
Thread.interrupt();
throw new RuntimeException("Not sure if you should continue doing stuff in case of interruption");
}
}
signalWaitingThreadsForMethodB.signalAll();
} finally {
threadsForMethodBLock.unlock();
}
//do stuff
}
So each thread entering methodB will first check if nobody in methodA, and signal previous waiting threads. On the other hand, each thread entering methodA will increment counter to prevent new threads doing work in methodB, and on decrement it will release all the threads waiting to do stuff in methodB if no threads left inside methodA.

How to stop my program from eternally waiting? (wait/notify multithreading issue)

I have three classes, one that is meant to represent a pile of urls
private Queue<String> queue = new LinkedList<String>();
public Queue<String> getQueue() {
return queue;
}
private int limit = 5;
private int stillParsing;
public synchronized String getNextString() throws InterruptedException {
while (queue.isEmpty()||stillParsing > limit) {
System.out.println("no for you "+ queue.peek());
wait();
}
System.out.println("grabbed");
notify();
stillParsing++;
System.out.println(queue.peek());
return queue.remove();
}
public synchronized void doneParsing() {
stillParsing--;
}
}
A thread class whose run method is
public void run(){
try {
sleep(30);
for(;;){
String currenturl = pile.getNextString();
//(do things)
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
pile.doneParsing();
}
}
And a mapper that actually adds objects into the pile of urls using this snipet
while (urls.hasMoreTokens()) {
try{
word.set(urls.nextToken());
String currenturl = word.toString();
System.out.println(currenturl);
pile.getQueue().add(currenturl);
From debugging what I think happens is that all of the threads try to get from the queue at once before the mapper has a chance to populate it and they get stuck waiting. Unfortunately all of the threads waiting is causing my program to hang up and not add more urls to the queue. How should I go about taking care of this issue? Preferably while still using wait notify.
while (urls.hasMoreTokens()) {
try {
word.set(urls.nextToken());
String currenturl = word.toString();
System.out.println(currenturl);
pile.getQueue().add(currenturl);
In the above code, you're breaking the encapsulation of the pile by adding something to its queue without going though a method of the pile. You should not have a getQueue() method in this class: all the accesses to this shared data structure should be synchronized on the same lock. You should thus add a synchronized method allowing to add a URL to the queue. And this method should also call notify() (or better: notifyAll()), in order to wake up the threads that are waiting for some element to be in the queue:
public synchronized void addUrl(String url) {
queue.add(url);
notifyAll();
}
Even without reading all lines of your code and explanations I can say that your usage of wait and notify are buggy.
Method wait() is blocking. It exits only when notify() on the same monitor is called. This means that you cannot put both wait() and notify() from the same thread. You simply never arrive to notify() because wait() is blocked forever.
Other version of wait(): wait(timeout) is blocked but is limited by specified timeout.
Moreover wait/notify pair work only if they are written into synchronized block:
// thread-1
synchronoized(obj) {
obj.wait();
}
// thread-2
synchronoized(obj) {
obj.notify();
}
Thread-1 will exit wait when thread-2 calls notify.

Can I implement park/unpark methods in pure Java?

I know LockSupport is part of the JDK, but I am wondering if the implementation below is semantically correct. Observe that Object.wait can deal with the problem of thread's interrupt. My question is not regarding performance; however, I will appreciate any suggestion to improve my solution as long as your solution only uses basic construction like wait, notify and synchronized.
Thanks a lot.
final class LockSupport {
static void park(long time) {
Thread th = Thread.currentThread();
if (th instanceof MyThread) {
MyThread h = (MyThread)th;
synchronized (h.obj) {
if (h.permit) {
h.permit = false;
return;
}
try {
h.obj.wait(time);
} catch (InterruptedException e) { }
}
}
}
static void unpark(MyThread h) {
synchronized (h.obj) {
h.permit = true;
h.obj.notify();
}
}
}
abstract class MyThread extends Thread {
public Object obj = new Object();
public boolean permit = true;
}
Initial permit should be false.
When an interrupt is caught, you need to re-interrupt the current thread
catch (InterruptedException e) { th.interrupt(); }
because if park() returns due to interrupt, the interrupt status should be set (see javadoc example)
After wait() completes, normally or abruptly due to interrupt, consume the permit.
In unpark(), if permit is already true, there's no need to notify.

Creating multithreading java class to process data

I would like to realize class in Java, which will be wait for new data from different threads and when he got it, this class will process it and again go to wait new data. I want to realize this using only synchronized, wait, notifyAll commands. I tried some variants:
1) using one thread, which wait by command lockObject.wait(). But when all active threads finish their work, this thread will be waiting forever. Of course, I can make method stopProcess(), but it is not safety, because another programmer can forget to call it.
2) using one daemon-thread, it will not work, because when all active threads finish their work, my daemon-thread die, but he can have some data which he must to process
3)when new data is coming - create new thread, which will process data. while thread is alive(he process given data), he will receive new data. when it is no data coming and all old data was processed, thread finish to work. Minus of this variant is - when data is coming through some period (when thread have time to process old data and die), a new thread will be created. I think it's bad for performance or/and memory. Am I right?
Is it possible to solve my problem using only one or two(may be using daemon and active thread in combination) threads and not using stopProcess() method??
Here some code
My realize of blocking queue
public class BlockingQueue<T> {
private Queue<T> queue = new LinkedList<T>();
public void add(T el){
synchronized (queue){
queue.add(el);
}
}
public T getFirst(){
synchronized (queue){
return queue.poll();
}
}
public int getSize(){
synchronized (queue){
return queue.size();
}
}
}
Data class
public class Data {
//some data
public void process(){
//process this data
}
}
First variant of code
public class ProcessData {
private BlockingQueue<Data> queue = new BlockingQueue<Data>();
private boolean run = false;
private Thread processThread;
private Object lock = new Object();
public synchronized void addData(Data data) throws Exception {
if (run){
if (data != null){
queue.add(data);
wakeUpToProcess();
}
}else{
throw new Exception("");
}
}
public synchronized void start() {
if (!run){
run = true;
processThread = new Thread(new Runnable() {
public void run() {
while (run || queue.getSize()!=0){
while(queue.getSize() == 0 && run){
//if stopProcess was not called
//and no active threads
//it will not die
waitForNewData();
}
Data cur;
while(queue.getSize() > 0){
cur = queue.getFirst();
cur.process();
}
}
}
});
processThread.start();
}
}
public synchronized void stopProcess() {
if (run){
run = false;
wakeUpToProcess();
}
}
private void waitForNewData(){
try{
synchronized (lock){
lock.wait();
}
}catch (InterruptedException ex){
ex.printStackTrace();
}
}
private void wakeUpToProcess(){
synchronized (lock){
lock.notifyAll();
}
}
}
In second variant I make processThread as daemon. But when active threads die, processThread finish to work, but there are some data in queue, which i have to process.
Third variant
public class ProcessData {
private BlockingQueue<Data> queue = new BlockingQueue<Data>();
private boolean run = false;
private Thread processThread = null;
public synchronized void addData(Data data) throws Exception {
if (run){
if (data != null){
queue.add(data);
wakeExecutor();
}
}else{
throw new Exception("ProcessData is stopped!");
}
}
public synchronized void start() {
if (!run){
run = true;
}
}
public synchronized void stopProcess() {
if (run){
run = false;
}
}
public boolean isRunning(){
return this.run;
}
protected void wakeExecutor(){
if (processThread ==null || !processThread.isAlive()){
processThread = new Thread(new Runnable() {
#Override
public void run() {
Data cur;
while(queue.getSize() > 0){
cur = queue.getFirst();
cur.process();
}
}
});
processThread.start();
}
}
}
It is important, that data must to process in the order, in which it come from threads.
You are seriously reinventing the wheel here. All you want is available in the JDK in the java.util.concurrent package.
Implement a producer-consumer pattern via a BlockingQueue, with your producers calling offer() and your consumer thread calling take(), which blocks until something's available.
That's it. You don't need, and you shouldn't be writing, all those classes you have written. These concurrent classes do all the locking and synchronization for you, and do it correctly too (which is not to be underestimated)
If you're not allowed to use anything from java.util.concurrent then you'll have to implement your own task queue based on something like a LinkedList. I would encapsulate the blocking behaviour in the queue, e.g. (pseudocode)
synchronized Data nextTask() {
while(the linked list is empty) {
wait()
}
remove and return head of the queue
}
synchronized void addTask(Data d) {
add d to the queue
notifyAll()
}
Then you can just have a consumer thread that continuously does something like this
while(true) {
taskQueue.nextTask().process()
}
and the producer threads call taskQueue.addTask to add each task to the queue. If you need a graceful shutdown at the end then you'll either need some "sentinel value" to tell the consumer thread to finish, or find some way of calling Thread.interrupt() at the right time.

Why does java thread wait() work only with time limit in here?

I am trying to get familiar with Java threads for the SCJP and I had a question.
In the below-written code i simply created:
two Runnables with
a common data storage (an array) and
a synchronized write() method to fill it with data successively leaving a letter as a mark for each Runnable (A and B) in sequence.
I know the code is rough and could be better written but I was seeking the moral of the threads.
So now when I run it, it never terminates and the results stop at:
Still good.
A0.
But when I change wait() to wait(100) it works just fine counting from 0 to 9 and it terminates normally. Could someone explain the reason behind that for me please?
Thank you.
public class ArrayThreads {
Object[] array = new Object[10];
boolean isA = true;
int position = 0;
int getIndex(){
return position;
}
class ThreadA implements Runnable{
synchronized void write(String value){
while(!isA){
try {
wait();
} catch (InterruptedException ex) {
System.out.println("An error in" + value);
ex.printStackTrace();
}
}
array[position] = value + position;
System.out.println(array[position]);
position++;
isA = !isA;
notify();
}
public void run() {
while(getIndex()<array.length){
if (getIndex()==9) return;
else
write("A");}
}
}
class ThreadB implements Runnable{
synchronized void write(String value){
while(isA){
try {
wait();
} catch (InterruptedException ex) {
System.out.println("An error in" + value);
ex.printStackTrace();
}
}
array[position] = value + position;
System.out.println(array[position]);
position++;
isA = !isA;
notify();
}
public void run() {
while(getIndex()<array.length){
if (getIndex()==9) return;
else
write("B");}
}
}
public static void main(String[] args){
ArrayThreads threads = new ArrayThreads();
Thread threadA = new Thread(threads.new ThreadA());
Thread threadB = new Thread(threads.new ThreadB());
System.out.println("Still good");
threadB.start();
threadA.start();
}
}
Your threads are each waiting and notifying separate objects - so they're not communicating with each other at all. If you want them to effectively release each other, they'll need a shared monitor to synchronize, wait on and notify.
It's "working" when you specify a timeout because it's effectively turning the wait call into a sleep call... still nothing is really waiting/notifying usefully, because the two threads are still dealing with separate monitors.
your objects are not working in same monitor.
you need to either move the wait() and notify() to same object like:
http://www.java-samples.com/showtutorial.php?tutorialid=306
or you can notify the target object:
http://www.linuxtopia.org/online_books/programming_books/thinking_in_java/TIJ315_016.htm
when you set wait(100). you are setting a timeout. and definitely it will wake up after 100ms.

Categories

Resources