I have a problem with Java. I would like to write a program where there is Class Main which has ArrayList of Threads of some class (Class Task) which just writes a letter and the number. Object Main just wakes one Thread from ArrayList and let it to do something while the same object(Main) sleeps another one.
It works ok:
0A, 0B, 0C, 1B, 1C, 1A, 2B, 2A, 2C, 3B, 3C, 3A, 4B, 4C, 4A, 5B, 5A, 5C,
but only if i Comment the:
e.printStackTrace() e is Exception
then
I get lot of
java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at Main.run(Main.java:22)
So the notify works wrong, how I should correctly wake it, please tell me, show, correct. PLease
import java.util.ArrayList;
import java.util.ArrayList;
public class Main extends Thread {
ArrayList<Thread> threads;
public Main() {
super();
threads = new ArrayList<Thread>();
}
public void run() {
for (int i = 0; i < 3; i++) {
threads.add(new Thread(new Task(i + 65)));
}
long cT = System.currentTimeMillis();
for (int i = 0; i < threads.size(); i++) {
threads.get(i).start();
}
while (System.currentTimeMillis() - cT < 10000) {
for (int i = 0; i < threads.size(); i++) {
try {
threads.get(i).notify();
// HOW TO WAKE THREAD FROM threads ArrayList
Thread.sleep(1000);
// how to put to bed the same thread ?
threads.get(i).wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
new Main().start();
//new Thread(new Task(65)).start();
}
}
H
public class Task implements Runnable {
int nr;
char character;
public Task(int literaASCII) {
this.nr = 0;
character = (char) (literaASCII);
}
@Override
public void run() {
while (true) {
try {
System.out.print(nr + "" + character + ", ");
nr++;
int r = (int) ((Math.random() * 500) + 500); // <500ms,1000ms)
Thread.sleep(r);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
sleepandwaitare very different.sleepsimply pauses the current thread for the specified amount of time, and has no direct interaction with other threads.waitis more complicated: the idea ofwaitis to pause a thread on a given monitor (or lock, if you wish) and let other thread do work until itnotifys on that monitor and releases it. Sowaitandnotifyinvolves interaction between two or more threads.Because of this interaction, in order for
waitandnotifyto work correctly, the thread which calls those methods must own the monitor (the lock), which means, thatobject.wait()orobject.notify()must be called from withinsynchronized(object){ ... }block. If you callobject.wait()withoutsynchronized-block you will always get anIllegalMonitorStateException.In your code,
this will start all threads and then will run them all at the same time, not one at a time as you want.
To make sure only one thread runs one at a time you will need to pass a common monitor object to all threads and have them
waiton that monitor. For example:It may behave slightly differently from your original intention, because threads will wake up randomly, so there is no guarantee the output will be in any particular order.
Also note that in general you should prefer
notifyAll()tonotify(), unless you have a very good reason to usenotify(). Becausenotify()only wakes up one thread, if that thread “forgets” to call notify at the end, all other threads maywaitforever.