So I'm trying to implement a multi-threading java code to simulate a Message server and client. they share a common resource to communicate. Client should only be able to read the message when server notifies it, after receiving it from the user. this continues until user types "quit".
now, the below code works JUST FINE:
import java.util.Scanner;
class Message{
Scanner sc = new Scanner(System.in);
private String text="";
private boolean hasText;
public void writeText(){
while(hasText)
try{
wait();
}catch (InterruptedException e){ System.out.println(e.toString()); }
hasText = true;
System.out.print("Server wants you to enter a message: ");
text = sc.nextLine();
System.out.println("Server wrote the message: " + text);
notify();
}
public void readText(){
while(!hasText)
try{
wait();
}catch(InterruptedException e){System.out.println(e.toString());}
System.out.println("Client read the current message: " + text);
System.out.println("------------------------------");
hasText = false;
notify();
}
public String getText(){
return text;
}
}
class Server extends Thread{
final Message m;
Server(Message m){
this.m = m;
}
public void run(){
synchronized(m) {
while (!m.getText().equals("quit"))
m.writeText();
}
}
}
class Client extends Thread{
final Message m;
Client(Message m){
this.m = m;
}
public void run(){
synchronized (m) {
while (!m.getText().equals("quit"))
m.readText();
}
}
}
class B{
public static void main(String[] args){
Message m = new Message();
new Server(m).start();
new Client(m).start();
}
}
Output:
Server wants you to enter a message: lol
Server wrote the message: lol
Client read the current message: lol
------------------------------
Server wants you to enter a message: gg
Server wrote the message: gg
Client read the current message: gg
------------------------------
Server wants you to enter a message: quit
Server wrote the message: quit
Client read the current message: quit
------------------------------
but, when I try to implement the functions writeText() and readText() straight from the Server and Client class like this:
import java.util.Scanner;
class Message1{
public String text="";
public boolean hasText;
}
class Server1 extends Thread{
Message1 m;
Server1(Message1 m){
this.m = m;
}
public void run(){
synchronized(m) {
while (!m.text.equals("quit")){
while(m.hasText)
try{
wait();
}catch (InterruptedException e){ System.out.println(e.toString()); }
m.hasText = true;
System.out.print("Server wants you to enter a message: ");
Scanner sc = new Scanner(System.in);
m.text = sc.nextLine();
System.out.println("Server wrote the message: " + m.text);
notify();
}
}
}
}
class Client1 extends Thread{
Message1 m;
Client1(Message1 m){
this.m = m;
}
public void run(){
synchronized (m) {
while (!m.text.equals("quit")) {
while(!m.hasText)
try{
wait();
}catch(InterruptedException e){System.out.println(e.toString());}
System.out.println("Client read the current message: " + m.text);
System.out.println("------------------------------");
m.hasText = false;
notify();
}
}
}
}
class B1{
public static void main(String[] args){
Message1 m1 = new Message1();
new Server1(m1).start();
new Client1(m1).start();
}
}
it raises the IllegalMonitorStateException.
and i desperately want to know why. Ugh. Appreciate the help :))
ps, i also changed the access modifiers of my message class' text and flag, to avoid the usage of getters and setters.