Java Multithread code gives error-IllegalMonitorException - java

I was trying some concepts of multithreading learned recently but was not able to run it.
It gives IlleagalMonitorStateException but does not figure out the error why it is happening.
So about code-2 threads-reference names-filler & writter both are sharing an arraylist-filler is filling arraylist with integer(but will fill it upto 30) and after each number is added by filler and writter thread read the arraylist get the item writes it to file remove it from arraylist. For better understanding comment is added to code.
package com.utsav.pratice;
import java.io.*;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
//shared arraylist-synchronized
ArrayList<Integer> integerArrayList = new ArrayList<>();
//writter will write to this file numbers added to arraylist by filler and than will remove it from arraylist
FileOutputStream file = new FileOutputStream("Numbers.txt");
//filler will mark it true after completing all numbers
final boolean[] numbersCompleted = {false};
Thread filler=new Thread(new Runnable(){
#Override
public void run(){
//1-30 numbers one by one will be written to Arraylist
for (int i = 1; i < 31; i++) {
synchronized (integerArrayList) {
//if arraylist is not empty that means writter not performed on arraylist hence invoking wait to release lock so writter could perform
while(!integerArrayList.isEmpty()){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//so arraylist is empty now lets fill it,notify that releasing lock and than put thread to sleep
integerArrayList.add(i);
System.out.println("Number added");
if(i==30){
numbersCompleted[0] =true;}
notifyAll();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Numbers adding completed");
}
});
Thread writter=new Thread(new Runnable(){
#Override
public void run(){
//if numbers are completed than nothing to write come out of loop
while(!numbersCompleted[0]) {
synchronized (integerArrayList) {
//if arraylist is empty than its time for filler to work hence putting thread to wait so lock could be released for filler
while (integerArrayList.isEmpty()){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//so arraylist is not empty now lets write it & than remove it from arraylist,notify that releasing lock and than put thread to sleep
try (DataOutputStream fileWritter = new DataOutputStream(new BufferedOutputStream(file));) {
fileWritter.writeInt(integerArrayList.get(0));
System.out.println("Random number written");
} catch (IOException e) {
e.printStackTrace();
}
integerArrayList.remove(0);
notifyAll();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("File written completely");
}
});
//starting both threads-2cases filler takes the key-ok(will fill & wait) or filler takes the key(will wait since will be empty)
writter.start();
filler.start();

Here:
synchronized (integerArrayList)
You are synchronizing on your list.
But you are waiting/notify on this of your anonymous thread objects! And as the very first information in the javadoc says:
Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.
So things should work when you change those to
integerArrayList.wait()
for example (all usage of wait/notify/...) !
And hint: don't do things like
final ArrayList<Integer> integerArrayList = new ArrayList<>();
just go for
List<Integer> numbers = new ArrayList<>();
Simply do not use the concrete impl class type as type of your variable; and also not as part of its name!

Related

Java : Are sub threads lock the main thread? [duplicate]

This question already has answers here:
What's the difference between Thread start() and Runnable run()
(14 answers)
Closed 6 months ago.
I am new to Java, I have want to starts 02 thread to increase an attribute of an object and I want to print out the value of this attribute until it reach a certain value.
I use 02 threads started inside increaseByThread() method.
I use two code snippets as follows but they behave differently.
The first one I use while loop in the main thread to check for the value change but it only print out the last value after two sub-threads finish running and return 40.
The second one I use while loop but inside another sub-thread for checking value and it prints out every value, it means that 03 sub-threads are running in parallel (please see the second snippet below)
My question is that why in the first snippet, the while loop block only called after test.increaseByThread() finish execution?
public class ThreadIncrease {
public volatile int[] count={0};
public void increaseByThread(){
Runnable first= () -> {
for(int i=0;i<20;i++) {
count[0] = count[0] + 1;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// System.out.println(count[0]);
}
};
Runnable second= () -> {
for(int i=0;i<20;i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count[0] = count[0] + 1;
// System.out.println(count[0]);
}
};
Thread firstThread=new Thread(first);
Thread secondThread=new Thread(second);
firstThread.run();
secondThread.run();
}
public static void main(String[] args) {
ThreadIncrease test=new ThreadIncrease();
Runnable check=()->{
while(true){
System.out.println(test.count[0]);
if(test.count[0]<10){
System.out.println("count is: "+test.count[0]);
}
else{
System.out.println("Break");
break;
}
}
};
// Thread checkThread=new Thread(check);
// checkThread.start();
test.increaseByThread();
while(true){
System.out.println(test.count[0]);
if(test.count[0]<10){
System.out.println("count is: "+test.count[0]);
}
else{
System.out.println("Break");
break;
}
}
}
}
The second one I use while loop but inside another sub-thread for checking value and it prints out every value, it means that 03 sub-threads are running in parallel:
public class ThreadIncrease {
public volatile int[] count={0};
public void increaseByThread(){
Runnable first= () -> {
for(int i=0;i<20;i++) {
count[0] = count[0] + 1;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// System.out.println(count[0]);
}
};
Runnable second= () -> {
for(int i=0;i<20;i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count[0] = count[0] + 1;
// System.out.println(count[0]);
}
};
Thread firstThread=new Thread(first);
Thread secondThread=new Thread(second);
firstThread.run();
secondThread.run();
}
public static void main(String[] args) {
ThreadIncrease test=new ThreadIncrease();
Runnable check=()->{
while(true){
System.out.println(test.count[0]);
if(test.count[0]<10){
System.out.println("count is: "+test.count[0]);
}
else{
System.out.println("Break");
break;
}
}
};
Thread checkThread=new Thread(check);
checkThread.start();
test.increaseByThread();
// while(true){
// System.out.println(test.count[0]);
// if(test.count[0]<10){
// System.out.println("count is: "+test.count[0]);
// }
// else{
// System.out.println("Break");
// break;
// }
// }
}
}
You have not started any new thread yet.
Each thread needs to run something. That is it's run method. But by invoking thread.run you just execute that code on the calling thread, which is your main thread.
Instead you need to start the new thread using thread.start(). This function will return immediately, and the newly created thread will execute run() in parallel.
Since you were running everything on the main thread the perception is right that the main thread was blocked until all the runs finished.
Thread.run(), which you are calling in increaseByThread() runs the Thread's Runnable in the current thread. I think you have confused it with Thread.start(), which starts a new thread to run the Runnable.
See What's the difference between Thread start() and Runnable run() and When would you call java's thread.run() instead of thread.start()?

Simple thread program to understand synchronized, wait and notify

I'm looking at other examples here and in other sites and I'm not understanding what I'm doing wrong. I'm trying to do a program that one thread sets the value of an object to the values 1 to 10, but I want to wait for it to change the value until other thread reads it, so I can print them and have a list from 1 to 10.
My readThread run method just loops from 1 to 10 calling the following method:
private synchronized int receive() {
try {
wait();
int value = this.mainThread.getValor();
notify();
return value;
} catch (InterruptedException e) {
e.printStackTrace();
}
return -1;
}
My writeThread run method just loops from 1 to 10 calling the following method:
private synchronized void send(int n) {
try {
this.mainThread.setValor(n);
notify();
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
The main method is the following:
public static void main(String[] args) {
MainThread mt = new MainThread();
ReadThread rt = new ReadThread(mt);
WriteThread wt = new WriteThread(mt);
wt.start();
rt.start();
}
The class MainThead has the property "valor" defined with its getter and setter
Thank you for your help
There are a couple of obvious problems.
It looks as if you are synchronising on the same lock (there isn't enough code to be 100% sure). Generally you should create an object specifically to use as a lock.
send may be executed before receive. In that case the first notify will do nothing, and both threads will stall in wait.
In theory, there is no guarantee that wait will not wakeup spontaneously. For this and other reasons, you really want the wait inside a while loop.

Can anyone explain this program? We cannot start a thread twice but we are getting an output 1-20.. can anyone explain?

import java.io.IOException;
public class Test implements Runnable {
private int m, n;
public synchronized void run() {
try {
for (int i = 0; i < 10; i++) {
m++;
n++;
Thread.sleep(100);
System.out.println(m + ", " + n);
}
} catch (InterruptedException e) {
}
}
public static void main(String[] args) {
try {
Test a = new Test();
new Thread(a).start();
new Thread(a).start();
} catch (Exception e) {
}
}
}
You are correct that you cannot start the same thread twice. But you aren't doing that here. You are starting two separate threads once each.
Your code is essentially the same as:
Thread t1 = new Thread(a);
t1.start();
Thread t2 = new Thread(a);
t2.start();
You are declaring 2 different threads and running them one after another. If you add the following code.
public synchronized void run() {
System.out.println("thread started");
try {
for (int i = 0; i < 10; i++) {
m++;
n++;
Thread.sleep(100);
System.out.println(m + ", " + n);
}
} catch (InterruptedException e) {
}
System.out.println("thread fininshed");
}
You can easily see where the first thread ends and then the second thread starts.
Each of your threads needs to execute task described in instance of Test class. More precisely in its run method. In your case both threads will need to execute task of Test but they will also need to use same instance of this class (which is stored in a reference).
Problem is that run method is synchronized which means it uses monitor/lock of current instance (this - available via a reference) which means that both threads can't execute it at the same time. To be more precise one of threads will need to wait until other thread will finish execution code from that synchronized block (which is entire body of run).
So in your case
one of your threads will print
enter synchronized block locked on a
print values in range 1-10
exit synchronized block locked on a
so now another thread can
enter synchronized block locked on a
print values in range 11-20 (since m and n will be increased each time in loop)
exit synchronized block locked on a

Writing to/Reading from a Vector (or ArrayList) with two threads

I have two threads both of which accesses an Vector. t1 adds a random number, while t2 removes and prints the first number. Below is the code and the output. t2 seems to execute only once (before t1 starts) and terminates forever. Am I missing something here? (PS: Tested with ArrayList as well)
import java.util.Random;
import java.util.Vector;
public class Main {
public static Vector<Integer> list1 = new Vector<Integer>();
public static void main(String[] args) throws InterruptedException {
System.out.println("Main started!");
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("writer started! ");
Random rand = new Random();
for(int i=0; i<10; i++) {
int x = rand.nextInt(100);
list1.add(x);
System.out.println("writer: " + x);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("reader started! ");
while(!list1.isEmpty()) {
int x = list1.remove(0);
System.out.println("reader: "+x);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
t2.start();
t1.start();
t1.join();
t2.join();
}
}
Output:
Main started!
reader started!
writer started!
writer: 40
writer: 9
writer: 23
writer: 5
writer: 41
writer: 29
writer: 72
writer: 73
writer: 95
writer: 46
This sounds like a toy to understand concurrency, so I didn't mention it before, but I will now (at the top because it is important).
If this is meant to be production code, don't roll your own. There are plenty of well implemented (debugged) concurrent data structures in java.util.concurrent. Use them.
When consuming, you need to not shutdown your consumer based on "all items consumed". This is due to a race condition where the consumer might "race ahead" of the producer and detect an empty list only because the producer hasn't yet written the items for consumption.
There are a number of ways to accomplish a shutdown of the consumer, but none of them can be done by looking at the data to be consumed in isolation.
My recommendation is that the producer "signals" the consumer when the producer is done producing. Then the consumer will stop when it has both the "signal" no more data is being produced AND the list is empty.
Alternative techniques include creating a "shutdown" item. The "producer" adds the shutdown item, and the consumer only shuts down when the "shutdown" item is seen. If you have a group of consumers, keep in mind that you shouldn't remove the shutdown item (or only one consumer would shutdown).
Also, the consumer could "monitor" the producer, such that if the producer is "alive / existent" and the list is empty, the consumer assumes that more data will become available. Shutdown occurs when the producer is dead / non-existent AND no data is available.
Which technique you use will depend on the approach you prefer and the problem you're trying to solve.
I know that people like the elegant solutions, but if your single producer is aware of the single consumer, the first option looks like.
public class Producer {
public void shutdown() {
addRemainingItems();
consumer.shutdown();
}
}
where the Consumer looks like {
public class Consumer {
private boolean shuttingDown = false;
public void shutdown() {
shuttingDown = true;
}
public void run() {
if (!list.isEmpty() && !shuttingDown) {
// pull item and process
}
}
}
Note that such lack of locking around items on the list is inherently dangerous, but you stated only a single consumer, so there's no contention for reading from the list.
Now if you have multiple consumers, you need to provide protections to assure that a single item isn't pulled by two threads at the same time (and need to communicate in such a manner that all threads shutdown).
I think this is a typical Producer–consumer problem. Try to have a look into Semaphore.
Update: The issue`s gone after changing the while loop in the consumer (reader). Instead of exiting the thread if the list is empty, it now enters the loop but does not do anything. Below is the updated reader thread. Of course a decent shutdown mechanism can also be added to the code such as Edwin suggested.
public void run() {
System.out.println("reader started! ");
while(true) {
if(!list1.isEmpty()) {
int x = list1.remove(0);
System.out.println("reader: "+x);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Please note, this is not a code snippet taken from a real product or will go in one!

Binary Semaphores and Buffers to sequentially print

I'm attempting to print a combination of characters.
Character 1 and 2 must be in sequence as follows: 1212121212. Character 3 prints intermittently, but must not exceed Character 2.
I have managed the first part of the task (1 and 2), but struggling with the introduction of 3. I know I need to use a counting semaphore to crack it.
This is for school, so please could you avoid pasting any code and just give me some pointers? I'm just showing two classes: my buffer, and Threads that print the characters.
Thanks.
public class PrintLetterA extends Thread {
private char letter;
private Buffer buffer;
public PrintLetterA(char letter, Buffer b) {
this.letter = letter;
buffer = b;
}
public void run() {
while (true) {
if (letter == 'F') {
Object a = new Object();
buffer.put(a);
System.out.println("" + letter);
try {
Thread.sleep( (int) Math.random() * 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else if (letter == 'G'){
Object a = buffer.get();
System.out.println("" + letter);
try {
Thread.sleep( (int) Math.random() * 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
public class Buffer {
private Object message = null;
BinarySemaphore Fbinary = new BinarySemaphore(1);
BinarySemaphore Gbinary = new BinarySemaphore(0);
public synchronized void put(Object message) {
try {
Fbinary.P();
} catch (InterruptedException e) {
e.printStackTrace();
}
this.message = message;
Gbinary.V();
}
public synchronized Object get() {
try {
Gbinary.P();
} catch (InterruptedException e) {
e.printStackTrace();
}
Object m = message;
Fbinary.V();
return m;
}
First of all, consider creating two different classes for your threads (and possibly a common abstract superclass) instead of the if/else fork inside the run().
Now, take a look at the Semaphore class, be sure to read the description in the beginning of that page, it is really helpful to understand the concept. Basically, there are two methods you care about: acquire and release. Each time you print your "2", you will call the release method. This increases the number of "permits" that the semaphore holds. Now, in the other thread, just before printing "3", you will call acquire, it will check if there are any permits available, and if not , it'll block and wait, otherwise, it will decrease the number, and return, so that you can print your "3".
When you use it this way, the number of permits held by the semaphore at any given moment will reflect how many more "2"s have been printed than "3"s so far. There will never be more 3s than 2s, because acquire will not allow the number of permits go negative, if it happens to be 0, it will force your thread to wait until the other one prints another "2" and calls "release".

Categories

Resources