The below program is supposed to print even and odd numbers by two different threads but I am getting illegal monitor exception on notify method in the below code :
public class oddeven {
static volatile Integer t = 0;
public static void main(String as[]) {
oddrunnable or = new oddrunnable(t);
evenrunnable er = new evenrunnable(t);
Thread t1 = new Thread(or, "odd");
Thread t2 = new Thread(er, "even");
t1.start();
t2.start();
}
}
class oddrunnable implements Runnable {
Integer t;
public oddrunnable(Integer t) {
this.t = t;
}
#Override
public void run() {
// TODO Auto-generated method stub
synchronized (t) {
while (true) {
if (t % 2 == 0) {
try {
t.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Current thread id " + Thread.currentThread().getName());
t++;
t.notify();
}
}
}
}
class evenrunnable implements Runnable {
Integer t;
public evenrunnable(Integer t) {
this.t = t;
}
#Override
public void run() {
// TODO Auto-generated method stub
// TODO Auto-generated method stub
synchronized (t) {
while (true) {
if (t % 2 != 0) {
try {
t.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Current thread id " + Thread.currentThread().getName());
t++;
t.notify(); // <-------------------exception on this line
}
}
}
}
the notify method is called on the synchronized object itself. Not sure why this is coming :
Current thread id even
Exception in thread "even" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at evenrunnable.run(oddeven.java:86)
at java.lang.Thread.run(Thread.java:619)
Integers in java wrapper are immutable, so as soon as you do t++, you are going to assign a new Integer object which you didn't took lock against and hence you get IllegalMonitorStateException.
Instead of Integer, use AtomicInteger and then use incrementAndGet api to increment the value of counter.
The problem is in using Integer object for synchronization and than doing increment(++) operation on it. I think its creating new integer object and than all the synchronized logic is going for toss. I am not sure about it as while debugging your code, eclipse was not showing whether it created new object.
A better alternative is to use some wrapper object around your integer or AtomicInteger class. Here is your code with AtomicInteger class used
public class oddeven {
static volatile AtomicInteger t = new AtomicInteger(0);
public static void main(String as[]) {
oddrunnable or = new oddrunnable(t);
evenrunnable er = new evenrunnable(t);
Thread t1 = new Thread(or, "odd");
Thread t2 = new Thread(er, "even");
t1.start();
t2.start();
}
}
class oddrunnable implements Runnable {
AtomicInteger t;
public oddrunnable(AtomicInteger t) {
this.t = t;
}
#Override
public void run() {
// TODO Auto-generated method stub
synchronized (t) {
while (true) {
if (t.intValue() % 2 == 0) {
try {
t.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Current thread id " + Thread.currentThread().getName());
t.incrementAndGet();
t.notify();
}
}
}
}
class evenrunnable implements Runnable {
AtomicInteger t;
public evenrunnable(AtomicInteger t) {
this.t = t;
}
#Override
public void run() {
// TODO Auto-generated method stub
// TODO Auto-generated method stub
synchronized (t) {
while (true) {
if (t.intValue() % 2 != 0) {
try {
t.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Current thread id " + Thread.currentThread().getName());
t.incrementAndGet();
t.notify(); // <-------------------exception on this line
}
}
}
}
Related
I created two separate threads one for writing into a list and second for removing from the list.
package com.produ.consu;
public class Test {
public static void main(String[] args) {
Operations operations = new Operations();
Runnable r1 = new ThreadsClass(operations);
Runnable r2 = new ThreadsClass(operations);
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.setName("READ");
t2.setName("WRITE");
t1.start();
t2.start();
}
}
Above is Test class where I created threads.
package com.produ.consu;
public class ThreadsClass implements Runnable {
Operations operations;
ThreadsClass(Operations operations){
this.operations=operations;
}
#Override
public void run() {
// TODO Auto-generated method stub
if(Thread.currentThread().getName().equals("WRITE")) {
operations.writeList();
}
else {
operations.readList();
}
}
}
Above is class calling synchronized methods based on the thread name:
import java.util.ArrayList;
import java.util.List;
public class Operations {
List<Integer> list=null;
int count=0;
boolean flag;
Operations(){
list=new ArrayList<>();
flag=true;
}
public synchronized void writeList() {
// TODO Auto-generated method stub
while(true) {
if(flag) {
count++;
list.add(count);
System.out.println("inise if block...."+Thread.currentThread().getName());
System.out.println(list);
flag=false;
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else {
notify();
}
}
}
public synchronized void readList() {
// TODO Auto-generated method stub
while(true) {
if(!flag) {
Integer i = list.remove(0);
System.out.println(i+"..removed at index by"+Thread.currentThread().getName());
flag=true;
notify();
}
else {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
Above is where I mentioned functionality.
So write thread hast to write element to list and wait until it is removed by the second thread.
Once removed second should notify 1st and wait for until element inserted.
But getting...
inise if block....WRITE [1]
Not even removed and it has to be a continuous process.
Give me suggestions on given code.
You should wait() inside the else block also, otherwise the while will continue to run if the if is not satisfied and the other thread won't get a chance to execute.
After the read/write operation is performed the thread should call notify to wake up the other thread and itself should go in the waiting state.
public synchronized void writeList() {
while (true) {
if (flag) {
count++;
list.add(count);
System.out.println("inise if block...." + Thread.currentThread().getName());
System.out.println(list);
flag = false;
try {
notify(); //notify the read thread that write is complete
wait(); // go into the waiting state so that no further write is done until the current element is removed by the read thread.
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
try {
wait(); //wait in else, otherwise while will run endlessly
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public synchronized void readList() {
while (true) {
System.out.println("in read");
if (!flag) {
Integer i = list.remove(0);
System.out.println(i + "..removed at index by" + Thread.currentThread().getName());
flag = true;
try {
notify(); //notify write thread that read is complete
wait(); //go into wait until new element is inserted
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
try {
wait(); //wait in else otherwise while runs endlessly
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
You should replace the method synchronization with more granular synchronization: wrap the operations that access the list and update count with a synchronized block.
Alternatively, use a linked blocking queue to pass “messages” between threads (or, in more advanced scenarios, a messaging solution such as Akka, Kafka, zeromq, or other similar solutions)
Since you only add one elemet at a time you could also use a Exchanger.
Take a look at the Java concurrent package.
import java.io.IOException;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Foo {
public static void main(String[] args) throws IOException, InterruptedException {
final Exchanger<Integer> exchanger = new Exchanger<>();
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> {
// producer
int count = 0;
while (!Thread.currentThread().isInterrupted()) {
try {
exchanger.exchange(count++);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
executorService.execute(() -> {
// reader
while (!Thread.currentThread().isInterrupted()) {
try {
System.out.println("consume " + exchanger.exchange(null));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
System.in.read();
executorService.shutdownNow();
executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("Shut down");
}
}
I'm taking one Integer variable and sharing with two threads. One thread should print even numbers and one thread should print odd number sequentially.
But notify() throwing IllegalMonitorStateException.
package mywaitnotifytest;
public class App {
public static void main(String[] args) {
Integer i=0;
Even even = new Even(i);
even.setName("EvenThread");
Odd odd = new Odd(i);
odd.setName("OddThread");
even.start();
odd.start();
}
}
class Even extends Thread{
Integer var;
Even(Integer var){
this.var=var;
}
#Override
public void run() {
while(true){
synchronized (var) {
if(var%2==0){
try {
var.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
var++;
System.out.println(Thread.currentThread().getName()+" "+var);
var.notify();
}
}
}
}
class Odd extends Thread{
Integer var;
Odd(Integer var){
this.var=var;
}
#Override
public void run() {
while(true){
synchronized (var) {
if(var%2!=0){
try {
var.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
var++;
System.out.println(Thread.currentThread().getName()+" "+var);
var.notify();
}
}
}
}
And the output is :
OddThread 1
Exception in thread "OddThread" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at mywaitnotifytest.Odd.run(App.java:67)
I think this is sufficiently different to the usual answer to give another one.
In this case you are using synchronized. When you apply a lock it is on a object not a reference.
synchronized (var) {
This locks the object var references, not on var as a field.
var++;
This replaces the object var points to. It is the same as
var = Integer.valueOf(var.intValue() + 1);
Note: Integer and indeed all the primitive wrappers are Immutable. When you perform any operation on them you are actually unboxing, calculating using the primitive value and re-boxing the object. It is possible to get the same object back if it is pooled. e.g.
Integer i = 10;
i += 0; // gives back the same object.
However, if the object is not pooled
Double d = 10;
d += 0; // creates a new object.
var.notify();
Attempts the call notify on the new object, not the one which was locked.
You shouldn't attempt to lock a field which you mutate. It won't do what it appears to do. You also shouldn't lock on a pooled object. In this case you could have another thread using the same Integer for an unrelated purpose and notify() will wake up an unrelated thread.
To use wait/notify correctly, you should
notify() or notifyAll() after a state change in another shared field.
you should use a while loop for wait() to check the state change.
If you don't do this
notify can be lost if another thread is not waiting.
wait can wake spuriously, even when no notify was called.
For the above requirement what is the edit suggested in the code? How do i share the same object for multiple threads?
public class PingPong implements Runnable {
static class Shared { int num; }
private final Shared var;
private final int bit;
public static void main(String[] args) {
Shared var = new Shared();
new Thread(new PingPong(var, 0), "EvenThread").start();
new Thread(new PingPong(var, 1), "OddThread").start();
}
PingPong(Shared var, int bit) {
this.var = var;
this.bit = bit;
}
#Override
public void run() {
try {
String name = Thread.currentThread().getName();
while (true) {
synchronized (var) {
while (var.num % 2 == bit)
var.wait();
var.num++;
System.out.println(name + " " + var.num);
var.notify();
}
}
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
}
}
Instead of using Integer wrapper class,I created my own class and now It works fine.
package mywaitnotifytest;
public class App {
public static void main(String[] args) {
MyInt i = new MyInt(0);
Even even = new Even(i);
even.setName("EvenThread");
Odd odd = new Odd(i);
odd.setName("OddThread");
even.start();
odd.start();
}
}
class Even extends Thread {
MyInt var;
Even(MyInt var) {
this.var = var;
}
#Override
public void run() {
while (true) {
try {
Thread.sleep(200);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
synchronized (var) {
if (var.i % 2 == 0) {
try {
var.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
var.i++;
System.out.println(Thread.currentThread().getName() + " " + var.i);
var.notify();
}
}
}
}
class Odd extends Thread {
MyInt var;
Odd(MyInt var) {
this.var = var;
}
#Override
public void run() {
while (true) {
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
synchronized (var) {
if (var.i % 2 != 0) {
try {
var.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
var.i++;
System.out.println(Thread.currentThread().getName() + " " + var.i);
var.notify();
}
}
}
}
class MyInt {
int i = 0;
public MyInt(int i) {
super();
this.i = i;
}
#Override
public String toString() {
// TODO Auto-generated method stub
return "" + i;
}
}
This my code ,the code run the end is not my excepted.
I think the PriorityBlockingQueue sorted by Priority but the end is not my expected,Who can told me why.
public class TestPriorityQueue {
static Random r=new Random(47);
public static void main(String args[]) throws InterruptedException{
final PriorityBlockingQueue q=new PriorityBlockingQueue();
ExecutorService se=Executors.newCachedThreadPool();
//execute producer
se.execute(new Runnable(){
public void run() {
int i=0;
while(true){
q.put(new PriorityEntity(r.nextInt(10),i++));
try {
TimeUnit.MILLISECONDS.sleep(r.nextInt(1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
//execute consumer
se.execute(new Runnable(){
public void run() {
while(true){
try {
System.out.println("take== "+q.take()+" left:== ["+q.toString()+"]");
try {
TimeUnit.MILLISECONDS.sleep(r.nextInt(1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("shutdown");
}
}
class PriorityEntity implements Comparable<PriorityEntity> {
private static int count=0;
private int id=count++;
private int priority;
private int index=0;
public PriorityEntity(int priority,int index) {
this.priority = priority;
this.index=index;
}
public String toString(){
return id+"* [index="+index+" priority="+priority+"]";
}
//数字大,优先级高
public int compareTo(PriorityEntity o) {
return this.priority < o.priority ? 1
: this.priority > o.priority ? -1 : 0;
}
}
The following are the results,I would be very grateful to you for your help
Some observations:
in most cases the size of your queue was 1. Clearly, no sort order is relevant in any of those.
In a few cases the queue size may have been two, and in no such case does the output insinuate that an element of lower priority was preferred. I stress the verb "insinuate" because...
your code has no synchronized blocks so nothing prevents the following sequence of operations:
q.take(); // consumer thread
q.put(); // producer thread
q.toString(); // consumer thread
with the legitimate outcome of q.toString() showing an element of higher priority than was taken.
hello guys this is my code , problem am facing is that despite calling notifyAll, it is not releasing the lock , can you please state the reason and tell the solution. Am new to threads. Thanks in advance.
class Lock1 {}
class Home1 implements Runnable {
private static int i = 0;
private Lock1 object;
private Thread th;
public Home1(Lock1 ob, String t) {
object = ob;
th = new Thread(this);
th.start();
}
public void run() {
synchronized (object) {
while (i != 10) {
++i;
System.out.println(i);
}
try {
// System.out.println("here");
object.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("here thread 1");
}
}
}
class Home2 implements Runnable {
private static int i = 0;
private Lock1 object;
Thread th;
public Home2(Lock1 ob, String t) {
object = ob;
th = new Thread(this);
th.start();
}
public void run() {
synchronized (object) {
while (i != 10) {
++i;
System.out.println(i);
}
try {
// System.out.println("here");
object.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("here thread 2");
}
}
}
public class Locking {
public static void main(String arg[]) {
Lock1 ob = new Lock1();
new Home1(ob, "thread 1");
new Home2(ob, "thread 2");
synchronized (ob) {
ob.notifyAll();
}
}
}
When you use notifyAll, you should also have a state changed and when you use wait, you should check that state change.
In your case it is likely that notifyAll will be called long before the threads really have time to start. (For a computer, starting a thread takes an eternity, like 10,000,000 clock cycles) This means the notifyAll is lost. (It only notifies threads which are actually waiting right at that moment)
I have following classes :
package com.akshu.multithreading;
public class ThreadResource {
static int a;
static boolean Value =false;
public synchronized int getA() {
while(Value == false){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Value= false;
notify();
return a;
}
public synchronized void setA(int a) {
while(Value == true)
{
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
ThreadResource.a = a;
Value=true;
notify();
}
}
------------------
/**
*
*/
package com.akshu.multithreading;
/**
* #author akshu
*
*/
public class MyThreadA implements Runnable {
int a = 0;
ThreadResource tR= new ThreadResource();
#Override
public void run() {
for (int i = 0; i < 15; i++) {
tR.setA(++a);
System.out.println(" value of a :"+a);
}
}
}
------------
package com.akshu.multithreading;
public class MyThreadB implements Runnable {
#Override
public void run() {
// TODO Auto-generated method stub
ThreadResource tR =new ThreadResource();
for (int i = 0; i < 15; i++) {
System.out.println("getA()"+tR.getA());
}
}
}
----
package com.akshu.multithreading;
public class ThreadExecutionPoint {
public static void main(String args[]) {
Thread th1 = new Thread(new MyThreadA());
Thread th2 = new Thread(new MyThreadB());
th1.start();
th2.start();
}
}
I am trying to understand producer consumer problem via above code .When i execute the above code i am getting
value of a :1
getA()1
Program gets stuck here only (do not gets terminate).
Someone Please explain what wrong i am doing here?
Declare Value as volatile
I.e. static volatile boolean Value =false;
You have declared your set/get methods synchronized. This means that they are lock on this (the object's intrinsic lock).
But in your code you instantiate a different ThreadResource for each thread thereby not making them synchronized since this is different for each case.
Change your code as follows:
public class MyThreadA implements Runnable {
ThreadResource tR;
public MyThreadA(ThreadResource tr) {
this.tR = tr;
}
// your run method here NOT declaring a ThreadResource anymore!!!
}
and same for MyThreadB
Then in ThreadExecutionPoint
ThreadResource tr = new ThreadResource();
Thread th1 = new Thread(new MyThreadA(tr));
Thread th2 = new Thread(new MyThreadB(tr));