Java Threads: Wait Notify mechanism with ArrayList - java

I tried implementing wait/notify mechanism to modify the ArrayList using two separate threads.
It seems to work fine for first iteration but then for second iteration it waits forever in addToArray() method. I am not able to figure out why is it waiting forever in the method? As per my understanding the other thread (removing an item) should pick up when other thread goes to wait.
Please have a look and point out possible bug if any. I know I can use Vector to have thread-safe operation but that is not what I want.
package threadTest;
import java.util.*;
public class DhagaJava {
public static void main(String...strings){
ArrayModification am = new ArrayModification();
Thread t1 = new Thread(new AddToArray(am));
Thread t2 = new Thread(new RemoveFromArray(am));
t1.start();
t2.start();
}
}
class ArrayModification{
boolean added = false;
ArrayList<Integer> al;
ArrayModification(){
al = new ArrayList<Integer>();
}
public synchronized void addToArrayList(int x) {
if (added == true){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.al.add(x);
System.out.println(al);
System.out.println("Added!! :)");
added = true;
notifyAll();
}
public synchronized void removeFromList(){
if( added== false){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(al);
this.al.remove(0);
System.out.println("Removed!! :' ");
added = false;
notifyAll();
}
}
class AddToArray implements Runnable{
ArrayModification ma;
AddToArray(ArrayModification m){
this.ma = m;
}
public void run() {
for (int i = 0; i<10; i++)
ma.addToArrayList(i);
}
}
class RemoveFromArray implements Runnable{
ArrayModification ma;
RemoveFromArray(ArrayModification a){
this.ma = a;
}
public void run(){
ma.removeFromList();
}
}
class RemoveFromArray implements Runnable{
ArrayModification ma;
RemoveFromArray(ArrayModification a){
this.ma = a;
}
public void run(){
//for(int j=11;j<20; j++)
ma.removeFromList();
}
}
Output is:
[0]
Added!! :)
[0]
Removed!! :'
[1]
Added!! :)

Only problem you have is the removeFromList runs only once (because you commended out the for loop). That’s the reason why there is no second remove in the log and that addToArrayList starts waiting forever (waits for someone remove the item from the list).
I tried your code after removing the comment and works fine!

Rather than re-invent the wheel, just use a CopyOnWriteArrayList. It comes with concurrency out of the box.

Your notifyAll is inside the synchronized block. So the other thread may be awaken before he can act. So it may be blocked.
I'm not sure I understood your goal, but this construction could be better :
public void addToArrayList(int x) {
synchonized(this.al) {
if (added == true){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.al.add(x);
System.out.println(al);
System.out.println("Added!! :)");
added = true;
}
notifyAll();
}
But this is very complex. Do you have a more general goal ? Maybe a task queue with only one thread could suit you better : it would be faster, lighter, simpler, and as parallelized (that is not at all).

Related

Java Threads: How to print alphabets and numbers using two threads one at a time

I am trying to work around with threads in java. Though I understand that threads output are unpredictable, However was wondering if there is a way to do that.
I have to implement two threads, one prints alphabets(a,b,c...z) and other prints numbers(1,2,3....26). Have to implement it in such a way that the output should be a,1,b,2,c,3,d,4......z,26. Below is my code but it doesn't give the desired output.
public class ThreadsExample {
public static void main(String[] args) {
Runnable r = new Runnable1();
Thread t = new Thread(r);
Runnable r2 = new Runnable2();
Thread t2 = new Thread(r2);
t.start();
t2.start();
}
}
class Runnable2 implements Runnable{
public void run(){
for(char i='a';i<='z';i++) {
System.out.print(i+",");
}
}
}
class Runnable1 implements Runnable{
public void run(){
for(int i=1;i<=26;i++) {
System.out.print(i+",");
}
}
}
What tweak should I make in the code to get the desired output? How does synchronization helps here? Or is it really possible when working with Threads at all?
PS: This is not an assignment or some exercise. Its self learning.
It is possible. You need to synchronize it well.
Approach Pseudocode
query some (synchronized) state
state will tell whether nums or chars are allowed
if state allows char and caller will put chars, do it now and change state and wake up waiting threads
if not, wait
if state allows numbers and caller will put numbers, do it now and change state and wake up waiting threads
if not, wait
Java code
public class ThreadsExample {
public static ThreadsExample output = new ThreadsExample ();
public static void main(String[] args) {
Runnable r = new Runnable1();
Thread t = new Thread(r);
Runnable r2 = new Runnable2();
Thread t2 = new Thread(r2);
t.start();
t2.start();
}
private Object syncher = new Object (); // we use an explicit synch Object, you could use annotation on methods, too. like ABHISHEK did.
// explicit allows to deal with more complex situations, especially you could have more the one locking Object
private int state = 0; // 0 allows chars, 1 allows ints
public void print (char pChar) {
synchronized (syncher) { // prevent the other print to access state
while (true) {
if (state == 0) { // char are allowed
System.out.print(pChar + ","); // print it
state = 1; // now allow ints
syncher.notify(); // wake up all waiting threads
return;
} else { // not allowed for now
try {
syncher.wait(); // wait on wake up
} catch (InterruptedException e) {
}
}
}
}
}
public void print (int pInt) {
synchronized (syncher) {
while (true) {
if (state == 1) {
System.out.print(pInt + ",");
state = 0;
syncher.notify();
return;
} else {
try {
syncher.wait();
} catch (InterruptedException e) {
}
}
}
}
}
}
class Runnable2 implements Runnable{
public void run(){
for(char i='a';i<='z';i++) {
ThreadsExample.output.print(i);
}
}
}
class Runnable1 implements Runnable{
public void run(){
for(int i=1;i<=26;i++) {
ThreadsExample.output.print(i);
}
}
}
Output
a,1,b,2,c,3,d,4,e,5,f,6,g,7,h,8,i,9,j,10,k,11,l,12,m,13,n,14,o,15,p,16,q,17,r,18,s,19,t,20,u,21,v,22,w,23,x,24,y,25,z,26,
The whole idea of threads: it represents a "stream of activity" that executes code independent of other threads.
In your case, you want that these two threads go in "lockstep". Thread A does one step, then Thread B, then A, then B.
In order to get there, the two threads need something "synchronize" on - in other words: A sends a signal to B when it has done its steps - and B has to wait for that signal. Then B does its thing, signals to A, ...
For starters, a simple boolean value would do. One thread sets it to true, the other to false (to indicate when it has made its step). Then the thread waits for the boolean to toggle again.
As you intend to learn things, I would just start experimenting from there. In case you want to take detours, look here for example. This might help as well.
HERE IS THE CODE::
You need to create 2 threads and implement wait and notify methods correctly you can also refer "Create two threads, one display odd & other even numbers" for your answer.
public class ThreadClass {
volatile int i = 1;
volatile Character c = 'a';
volatile boolean state = true;
synchronized public void printAlphabet() {
try {
while (!state) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " +c);
state = false;
c++;
notifyAll();
}
synchronized public void printNumbers() {
try {
while (state) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " + i);
state = true;
i++;
notifyAll();
}
public static void main(String[] args) {
ThreadClass threadClass = new ThreadClass();
Thread t1 = new Thread() {
int k = 0;
#Override
public void run() {
while (k < 26) {
threadClass.printAlphabet();
k++;
}
}
};
t1.setName("Thread1");
Thread t2 = new Thread() {
int j = 0;
#Override
public void run() {
while (j < 26) {
threadClass.printNumbers();
j++;
}
}
};
t2.setName("Thread2");
t1.start();
t2.start();
}
}
Your threads are running at the same time. But not the way you want it, as mentioned above. You will see blocks of data from thread 1 and then a block of data from thread 2; and this is because of thread scheduling. Thread 1 is just queuing its output before thread 2.
To test this theory, increase your output to a 1000 records for example as the alphabet and 26 numbers are not as large to see this.
By doing so, you will see these 'blocks' of data. There is a way to do what you mentioned, but it is not advisable as this is not demonstrating how threads actually work but rather you forcing it to work that way.
With less Code:
class MyRunnable implements Runnable {
private static int n = 1;
private static char c = 'a';
public void run() {
for (int i = 1; i <= 26; i++) {
synchronized (this) {
try {
notifyAll();
if (Thread.currentThread().getName().equals("A")) {
System.out.print(c + ",");
c++;
} else {
System.out.print(n + ",");
n++;
}
if (i != 26) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class PrintAlphabetNumberJob {
public static void main(String[] args) throws InterruptedException {
MyRunnable r = new MyRunnable();
Thread tAlphabet = new Thread(r, "A");
Thread tNumber = new Thread(r, "N");
tAlphabet.start();
Thread.sleep(100);
tNumber.start();
}
}

how to decide the looping condition for wait() in Java

I am understanding wait() in Java in regards to multithreaded, and as per the documentation, wait() should always be in a loop.
I have difficult in understanding what is the condition we have to give in the loop. Typically, I have seen:
synchornized(obj) {
while(some_condition) {
obj.wait();
}
// some other code
}
I am having difficulty in understanding the "condition" which is used in the loop within which we are keeping wait().
I tried to implement a scenario in which I created two different threads (two different classes implementing Runnable interface), for printing Odd and Even numbers, like: 1 ,2 ,3,4,5,6...
As this is inter-thread communication and we need synchronization, I am having difficulty in relating what is the condition on which I have to keep wait() in loop for these two different threads.
Any clues as to how to decipher this (the condition we keep in loop) greatly appreciated.
Here, maybe this few lines will push you in the right direction, as a follow up to my previous comments.
class LastPrintedMonitor {
public boolean wasLastEven = false;
}
class PrinterOdd implements Runnable {
LastPrintedMonitor monitor;
public PrinterOdd(LastPrintedMonitor monitor) {
this.monitor = monitor;
}
#Override
public void run() {
for (int i = 2; i < 40; i += 2) {
synchronized (monitor) {
while (!monitor.wasLastEven) {
try {
monitor.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i);
monitor.wasLastEven = false;
monitor.notifyAll();
}
}
}
}
class PrinterEven implements Runnable {
LastPrintedMonitor monitor;
public PrinterEven(LastPrintedMonitor monitor) {
this.monitor = monitor;
}
#Override
public void run() {
for (int i = 1; i < 40; i += 2) {
synchronized (monitor) {
while (monitor.wasLastEven) {
try {
monitor.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i);
monitor.wasLastEven = true;
monitor.notifyAll();
}
}
}
}
public class EvenOddPrinterDemo {
public static void main(String[] args) {
LastPrintedMonitor monitor = new LastPrintedMonitor();
Thread odd = new Thread(new PrinterOdd(monitor));
Thread even = new Thread(new PrinterEven(monitor));
odd.start();
even.start();
try {
odd.join();
even.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Done!");
}
}
You mentioned two classes so their synchronized methods will not be synchronized to each other. That's why we synchronized on monitor, as there has to be something that those two objects share to make them "hear" each other.
The looping condition should check whether the execution(threads of the current class) need to be temporarily paused.
Taking an example of famous producer-consumer problem, where in the producer will somehow looks like
synchronized(mySharedObj)
{
while(mySharedObj.length==maxSize)
{
mySharedObj.wait();
}
}
If there are n number of Producer Threads on mySharedObj, all will be waiting when the shared resource(mySharedObj) has reached its limit.

Java Interlocked Threads

I'm getting interlocked threads in somewhat simple producer/consumer (and based on examples correct) code.
There is a thread executing this:
public void append(final Object obj) {
buffer.add(obj);
if (buffer.size() >= BUFFER_MAX_SIZE) {
insertLock.lock();
switchLock.lock();
insertLock.unlock();
bufferFull.signal();
try {
bufferSwitch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
switchLock.unlock();
}
}
There is another thread with this code:
try {
insertLock.lock();
while (true) {
switchLock.lock();
insertLock.unlock();
bufferFull.await();
switchBuffers();
bufferSwitch.signal();
insertLock.lock();
switchLock.unlock();
if (insertBuffer.size() > 0) {
db.insert(insertBuffer);
insertBuffer.clear();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
As I mentioned it is based on the producer/consumer example on the Condition API documentation. I can't detect why both threads get stuck on the conditions await method.
Is there any error ? Looks like there is something my naked eyes can't see.
Thank you,
PS: Added working code.
Thread A does
insertLock.lock();
switchLock.lock();
and Thread B does
switchLock.lock();
....
insertLock.lock();
So if Thread A acquires insertLock while B gets switchLock, neither A nor B can proceed to the next line.
It's a clasic deadlock situation. You should always make sure the locks are getting locked in the same order.
For a producer/consumer problem with threads you could look at the BlockingQueue interface and its derived classes that java offers.
For example:
package cl.mds.migracion;
import java.util.concurrent.ArrayBlockingQueue;
public class Example {
static ArrayBlockingQueue<String> buffer = new ArrayBlockingQueue<String>(5);
static class Producer implements Runnable{
#Override
public void run() {
for (int i = 0; i < 10; i++){
try {
Thread.sleep(500); //seleep 500ms to simulate producer time
buffer.put(String.valueOf(i)); //put waits the thread until there is size in the queue.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
static class Consumer implements Runnable{
public void run() {
for (int i = 0; i < 10; i++){
try {
Thread.sleep(100); //seleep 100ms to simulate slower consumer tha producer
System.out.printf("Consuming %s ....%n",buffer.take()); //take waits the thread until there is something in the queue
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args){
System.out.printf("Starting producer/consumer ....%n");
new Thread(new Producer()).start();
new Thread(new Consumer()).start();
System.out.printf("Finishing ....%n");
}
}

how to alternate monitor acquiring of synchronized section by two groups of threads?

I research concurrecy in java. Recently I learn wait and notify methods meaning.
Now I think that sometimes I should to solve following problem:
I have
class ThreadGroup1 extends Thread
and
class ThreadGroup2 extends Thread
I have 300 instances of every Thread and start simultaneously (for example by means of CountDownLatch )
And I have synchronized section:
synchronized(SharedObjectBetweenThreads){...}
I want to get following behaviour:
instance of ThreadGroup1 acquire the section
instance of ThreadGroup2 acquire the section
instance of ThreadGroup1 acquire the section
instance of ThreadGroup2 acquire the section
and so on.
I think you understand what I want.
I know that if I would use wait and notify I cannot guarantee which next thread from waiting queue will acquire section.
How can I solve described issue?
P.S.
This issue relates with question "how to notify concrete thread?"
P.S.
my current sketch
public class ConditionTest {
public static void main(String [] args){
List<Thread> threads = new ArrayList<>();
for(int i=0 ;i<10;i++) {
threads.add(new Thread1());
threads.add(new Thread2());
}
for(Thread thread : threads){
thread.start();
}
}
public static synchronized void method() throws InterruptedException {
System.out.println(Thread.currentThread());
Thread.sleep(500);
}
}
class Thread1 extends Thread{
static int index =0;
int number;
#Override
public void run(){
try {
ConditionTest.method();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
#Override
public String toString(){
return "group1-" + number;
}
Thread1(){
number= index++;
}
}
class Thread2 extends Thread{
static int index =0;
int number;
#Override
public void run(){
try {
ConditionTest.method();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
#Override
public String toString(){
return "group2-" + number;
}
Thread2(){
number= index++;
}
}
please help to correct this.
According hoaz answer I got resolving.
please review this code:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ConditionTest {
static Integer CountThreadInGroup = 10;
public static void main(String[] args) throws InterruptedException {
Lock lock = new ReentrantLock();
boolean isFirstShouldExecute = true;
Condition isFirstExpected = lock.newCondition();
Condition isSecondExpected = lock.newCondition() ;
Synchronizator synchronizator = new Synchronizator(isFirstShouldExecute, lock,isFirstExpected,isSecondExpected);
List<Thread> threads = new ArrayList<>();
for (int i = 0; i < CountThreadInGroup; i++) {
threads.add(new Thread1(synchronizator));
}
for (Thread thread : threads) {
thread.start();
}
threads.clear();
Thread.sleep(100);
for (int i = 0; i < CountThreadInGroup; i++) {
threads.add(new Thread2(synchronizator));
}
for (Thread thread : threads) {
thread.start();
}
}
public static void method() throws InterruptedException {
System.out.println(Thread.currentThread());
Thread.sleep(500);
}
}
class Thread1 extends Thread {
static int index = 0;
int number;
private final Synchronizator synchronizator;
#Override
public void run() {
synchronizator.lock.lock();
try {
while (!synchronizator.isFirstExpected) {
synchronizator.isFirstShouldExecute.await();
System.out.println(Thread.currentThread() + " woke up");
}
ConditionTest.method();
synchronizator.isFirstExpected = false;
synchronizator.isSecondShouldExecute.signal();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} finally {
synchronizator.lock.unlock();
}
}
#Override
public String toString() {
return "\t\t\t group1-" + number;
}
Thread1(Synchronizator synchronizator) {
this.synchronizator = synchronizator;
number = index++;
}
}
class Thread2 extends Thread {
static int index = 0;
int number;
private final Synchronizator synchronizator;
#Override
public void run() {
synchronizator.lock.lock();
try {
while (synchronizator.isFirstExpected) {
synchronizator.isSecondShouldExecute.await();
System.out.println(Thread.currentThread() + " woke up");
}
ConditionTest.method();
synchronizator.isFirstExpected = true;
synchronizator.isFirstShouldExecute.signal();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} finally {
synchronizator.lock.unlock();
}
}
#Override
public String toString() {
return "\t\t\t\t\t\t group2-" + number;
}
Thread2(Synchronizator synchronizator) {
this.synchronizator = synchronizator;
number = index++;
}
}
class Synchronizator{
volatile boolean isFirstExpected ;
Lock lock ;
Condition isFirstShouldExecute;
Condition isSecondShouldExecute;
Synchronizator(boolean isFirstExpected, Lock lock, Condition isFirstShouldExecute, Condition isSecondShouldExecute){
this.isFirstExpected = isFirstExpected;
this.lock =lock;
this.isFirstShouldExecute = isFirstShouldExecute;
this.isSecondShouldExecute = isSecondShouldExecute;
}
}
You can find Condition and ReentrantLock classes useful in this case:
Lock lock = new ReentrantLock();
Condition threadGroup1 = lock.newCondition();
Condition threadGroup2 = lock.newCondition();
volatile boolean isFirstGroupRunning = true;
Pass all four to each thread in both groups. You can actually compose them into new class.
In first thread group use following code:
lock.lock();
try {
while (!isFirstGroupRunning) threadGroup2.await();
// do whatever you need to do in first thread
isFirstGroupRunning = false;
threadGroup1.signal();
} finally {
lock.unlock();
}
In second thread group do similar await / signal sequence:
lock.lock();
try {
while (isFirstGroupRunning) threadGroup1.await();
// do whatever you need to do in second thread
isFirstGroupRunning = true;
threadGroup2.signal();
} finally {
lock.unlock();
}
First, I suggest you not extend Thread nor call the class ThreadGroup1, etc. ThreadGroup is a core class, and there is typically no reason to extend Thread. The best way to handle the logic executed in a thread is to implement Runnable and pass instances of that class to new Thread(myRunnableInstance).
I don't think I understand what you want to really do, but it doesn't sound like threads are the way to go. Threads are meant to run multiple process at the same time, not to do them in a sequence.
It sounds like you might want a different concurrent design, maybe a 'producer consumer model' if you have two separate 'Thread groups' that are acquiring a synchronised block sequentially. In which case you could have both thread groups interacting with the same BlockingQueue. It really depends on what these threads are doing.
See
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html

exiting infinite wait of one thread with input from another in java

I am making a Java app which does something on a HotKey combination. I have an infinite while loop to wait for HotKey input to close, but it makes the app very CPU time costing.
Following is how my code looks in the simplest way:
static boolean isOpen = true;
void main()
{
....
add SomeHotKeyListener();
....
while(isOpen)
{ }
releaseResources();
}
void onHotKey(int hotKeyIdentifier)
{
if(hotKeyIdentifier == something)
do something;
if(hotKeyIdentifier == something)
isOpen = false;
}
I need a multi-threading approach to achieve this, or if someone has something better to fit in.
I recommend you read about the synchronized keyword in Java. Just Google it, and you should find a ton of examples and tutorials.
This should solve your case:
static boolean isOpen = true;
static Object lock = new Object();
void main()
{
....
add SomeHotKeyListener();
....
synchronized(lock)
{
while(isOpen)
{
try {
lock.wait()
} catch(InterruptedException e) {
}
}
}
releaseResources();
}
void onHotKey(int hotKeyIdentifier)
{
if(hotKeyIdentifier == something)
do something;
if(hotKeyIdentifier == something)
{
synchronized(lock)
{
isOpen = false;
lock.notify();
}
}
}
Infinite while loop can consume quite a lot of system resource. Using wait and notify is recommended. Also you have to declare your boolean volatile as otherwise there is no guarantee that the changes made by one thread is picked up by the other. Below is an example which does something in a separate thread and until interrupted by the calling thread based on a user input (an enter in this case). See also the example from Oracle here
import java.util.Scanner;
public class WaitTest implements Runnable {
private volatile boolean shutdown = false;
public static void main(String[] args) {
WaitTest w = new WaitTest();
new Thread(w).start();
System.out.println("Press any key to interrupt");
Scanner sc = new Scanner(System.in);
sc.nextLine();
w.triggerShutDown();
}
#Override
public void run() {
while (!shutdown) {
synchronized (this) {
try {
System.out.println("doing some silly things");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("Server shutdown successfully");
}
public synchronized void triggerShutDown() {
this.shutdown = true;
notify();
}
}

Categories