I got an assignment for university where I have to implement a hangman game with Threads in Java.
My problem is that I can't understand how to handle the threads.
In my code there is a GameLeader who prompts the GuessingPlayer to enter a char which he guesses in the startWord. After he did that (run()-method) he takes the message further.
The connection between the two players should be arranged with 'Messages' (own implemented class). It's working if I use run() instead of wait().
Can u help me to understand why the while loop is not working after the first entered message?
Thanks!
Class GameLeader:
public class GameLeader {
public static void main(String[] args) throws IOException {
GuessingPlayer guessingPlayer = new GuessingPlayer(userInterface);
String guess;
System.out.println("Please enter a startWord to begin!");
String startWord = userInterface.enterWord();
guessingPlayer.start();
while (attempts < 11) {
synchronized (guessingPlayer) {
System.out.println("It's your turn, Guessing Player!");
guessingPlayer.wait();
guess = guessingPlayer.message.toString();
if (startWord.contains(guess)) {
...
}
} else {
...
}
userInterface.mainMenu(guess);
}
}
}
}
Class GuessingPlayer:
public class GuessingPlayer extends Thread {
Message guessMessage;
private UserInterface userInterface;
GuessingPlayer(UserInterface userInterface) {
this.userInterface = userInterface;
}
#Override
public void run() {
synchronized (this) {
guessMessage = new Message(userInterface.enterWord());
notify();
}
}
}
I think you would be well served to review the course material on threads, and/or talk to your instructor. But, a few comments and suggestions:
I imagine the game leader is supposed to be a thread, and the player(s) are also supposed to be threads (as your current GuessingPlayer class is). These are all instantiated and started when your program starts by calling the start() method on the thread.
You don't have to call run, that gets called internally by the thread once it's started. But you probably want a loop in the run method that waits for the thread to be notified, and then repeats.
By "message passing" they mean something general like having a shared object or Queue that all the threads can read/write and have a reference to. One thread writes something in that object, and calls Thread.notify() to notify the other threads that something interesting has happened in that object. When that happens, the other thread will wake up right where it called the Thread.wait() method. Then it can check that shared object to see what's up.
http://web.mit.edu/6.005/www/fa14/classes/20-queues-locks/message-passing/
http://www.programcreek.com/2009/02/notify-and-wait-example/
Hope this helps.
You are using wait() method in a wrong way. You do not need an object reference to call wait() method. It is a method defined in Java's Object class.
Therefore, just write wait() instead of using guessingPlayer object reference.
Hope this helps. :)
Related
I know this is a bit naive question but I want to understand the basic working principle behind multi-threading in java. Consider the following code and say A is executed in Main thread and it starts execution of another worker thread ,defined in class B. I want to know that can B.func1 called from A and run method of B, be executed in parallel or not?
public class A {
public static void main(String[] args) {
B obj = new B();
obj.start();
obj.func1();
}
}
public class B extends Thread {
public B() {
//constructor
}
public void run() {
while(true) {
//do somethings
}
}
public void func1() {
//do someotherthings
}
}
There is no magic behind a method call. If you call method from a thread, it is called in exactly the same thread. So since obj.func1() is called from main, it will be run in the main thread. It doesn't matter which class it belongs to or whether or not it extends Thread.
The new thread starts by executing run. Everything called from run and so on will be executed in parallel to main.
It's important to understand the difference between a thread and a Thread.
A thread is an independent execution of your code. Often when we talk about how some method or another works we say things like, "It tests the variable x, and if x is less than zero it calls the foobar method..."
Ok, but what is the "it" in that sentence? It is not the method. Methods don't do anything. A method is just a list of instructions, like the list of chores that somebody left for their housemate to perform. The list doesn't do the chores, it's the housemate that does the work (or so we might hope).
The "it" is a thread. Threads are entities in the operating system that execute methods (i.e., they do the chores).
A Thread, on the other hand, is a Java object that your program can use to create and manage new threads. Your program creates a new Thread object by doing:
thread t = new Thread(...);
[Oops! See what I just did? It's not your program, that does the work, it's your program's main thread, or maybe some other thread in your program. It's an easy thing to forget!]
Anyway, it subsequently creates the new thread by calling t.start();
Once you understand all that, then Sergey Tachenov's answer becomes obvious: Calling the methods of a Thread object really is no different from calling methods of any other kind of object.
There are multiple issues with your code. I have corrected them and added one more statement to print Thread Name in func1().
Working code:
public class A {
public static void main(String args[]){
B obj = new B();
obj.start();
obj.func1();
}
}
class B extends Thread{
public B (){
//constructor
}
public void run(){
while(true){
//do somethings
}
}
public void func1 (){
//do someotherthings
System.out.println("Thread name="+Thread.currentThread().getName());
}
}
output:
Thread name=main
Since you are directly calling func1() from main method (A.java) , you will get Thread name = main in output.
If you add same print statement run() method, you will get output as : Thread name=Thread-0
I have a class that has the object "Card". This class keeps checking to see if the object is not null anymore. Only one other thread can update this object. Should I just do it like the code below? Use volatile?Syncronized? lock (which I dont know how to use really)? What do you recommend as easiest solution?
Class A{
public Card myCard = null;
public void keepCheck(){
while(myCard == null){
Thread.sleep(100)
}
//value updated
callAnotherMethod();
}
Another thread has following:
public void run(){
a.myCard = new Card(5);
}
What do you suggest?
You should use a proper wait event (see the Guarded Block tutorial), otherwise you run the risk of the "watching" thread seeing the reference before it sees completely initialized member fields of the Card. Also wait() will allow the thread to sleep instead of sucking up CPU in a tight while loop.
For example:
Class A {
private final Object cardMonitor = new Object();
private volatile Card myCard;
public void keepCheck () {
synchronized (cardMonitor) {
while (myCard == null) {
try {
cardMonitor.wait();
} catch (InterruptedException x) {
// either abort or ignore, your choice
}
}
}
callAnotherMethod();
}
public void run () {
synchronized (cardMonitor) {
myCard = new Card(5);
cardMonitor.notifyAll();
}
}
}
I made myCard private in the above example. I do recommend avoiding lots of public fields in a case like this, as the code could end up getting messy fast.
Also note that you do not need cardMonitor -- you could use the A itself, but having a separate monitor object lets you have finer control over synchronization.
Beware, with the above implementation, if run() is called while callAnotherMethod() is executing, it will change myCard which may break callAnotherMethod() (which you do not show). Moving callAnotherMethod() inside the synchronized block is one possible solution, but you have to decide what the appropriate strategy is there given your requirements.
The variable needs to be volatile when modifying from a different thread if you intend to poll for it, but a better solution is to use wait()/notify() or even a Semaphore to keep your other thread sleeping until myCard variable is initialized.
Looks like you have a classic producer/consumer case.
You can handle this case using wait()/notify() methods. See here for an example: How to use wait and notify in Java?
Or here, for more examples: http://www.programcreek.com/2009/02/notify-and-wait-example/
This question already has answers here:
Is this starvation?
(2 answers)
Closed 9 years ago.
During our lessons in the university, we learned about Threads and used the "Busy Waiting" method for an example of a Car waiting at a TrafficLight. For this task we build three classes:
TrafficLight (implements Runnable)
Car (implements Runnable)
Main
In our Main class we start two Threads, one of Car, and one of TrafficLight. The Car has the boolean attribute hasToWait. The run() method in this class works the way, that it works through a while loop as long as hasToWait == true. To change this, we have the notifyCar() method in the Car class, which is used by the TrafficLight. The run() method in TrafficLight runs through a Thread.sleep() to simulate a certain time of waiting.
Everything works fine at my Prof's but eventually I have serious problems with it. As long as the while loop in the Car class is empty. When I put in a System.out.println() - which is not empty, it works. But if the Syso is empty, the result is no displaying of the Text of the Run method.
Also it's working when the Thread.sleep() in TrafficLight is 0. Than it works with an empty while loop.
Here is my code:
Car.java:
package trafficlight;
public class Car implements Runnable {
private boolean hasToWait = true;
public void run() {
this.crossTrafficLight();
}
public void crossTrafficLight() {
while(hasToWait){ for(int i = 0; i<20; i++){System.out.println("123");}} // Busy waiting
System.out.println("Auto fährt über Ampel");
}
public void notifyCar() {
this.hasToWait = false;
System.out.println("Test");
}
}
TrafficLight.java:
package trafficlight;
public class TrafficLight implements Runnable {
private Car car;
public TrafficLight(Car car) {
this.car = car;
}
#Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.car.notifyCar();
}
}
Main.java:
package trafficlight;
public class Main {
public static void main(String[] args){
Car car = new Car();
TrafficLight tl = new TrafficLight(car);
new Thread(car).start();
new Thread(tl).start();
}
}
Where is the problem? Why does it work at my profs but not at my computer? I got the code 1:1 in my Eclipse Juno, using JRE 1.7
In addition to everything said in this other answer (just substitute your hasToWait for finished in that answer), the reason why the code starts working when you add a println is as follows:
println is a synchronized method;
you call it in both threads;
this creates a happens-before relationship between the two threads;
therefore the write to the boolean flag becomes visible to the child thread.
You could say that it starts working mostly by accident: you are piggybacking on the synchronization going on in println.
The real problem with your code is the instance field hasToWait. This field is being used by two threads. The car thread reads the value, and the traffic light thread updates the value after some time.
The access to this field must be synchronized in some way.
There are two ways to do this:
Use the synchronized keyword. Either by using a synchronized block at all places, where it is read or written, or - better - write a synchronized getter and a synchronized setter, then use the getter and the setter inside the Car class.
Use the volatile keyword. Just declare your field as volatile. This keyword exists for exactly that case. More information on volatile can be found in Oracle's Java Tutorials.
After reading the article about atomic access (see link above), it should be clear that option 2 (declaring volatile) is the far better option - for this use case.
Now to the difference you see between your computer and your professor's computer: As long as you are using a single-core-processor, you will see updates on an instance field in other threads as though they were synchronized, because the CPU does not have to synchronize these values in the other cores' cache areas. If you use a multi-core-processor, then the JVM is able to run threads on several cores. That means, that these cores have to synchronize values, and the volatile mechanism is exactly designed for that.
I have class Server and subclass ClientThread. ClientThread has methods receive() and broadcast(String[] msg) used to receive and send messages from/to clients connected to server.
Scheme:
public class Server extends Thread {
private ArrayList<ClientThread> clientThreads;
class ClientThread extends Thread {
public void broadcast(String[] msg) {...}
public void receive() {
...
if (msg.equals("CHANGED")) {
resumeOthers();
}
public void suspendOthers() {
for (ClientThread c: clientThreads)
if (c!=this)
try {
c.wait();
} catch (InterruptedException e) {}
}
public void resumeOthers() {
for (ClientThread c: clientThreads)
if (c!=this)
c.notify();
}
}
public void run() {
...
cmd = new String[1];
cmd[0] = "PROMPTCHANGE";
for (ClientThread currPlayer: clientThreads) {
currPlayer.broadcast(cmd);
currPlayer.suspendOthers();
}
}
}
Now, I would like to make this ClientThreads work one after another, like this:
1. ClientThread number 1 is calling method broadcast.
Now any other ClientThread existing is freezed
(they are stored in ArrayList on Server)
2. Client (another class) replies with a message that is being caught by receive()
Now this thread is freezed, and the next one starts running
Unfortunately, my approach doesn't work.
Could somebody explain me in details how to achieve that?
by calling Object.wait(), you are are suspending the CALLING thread, not the thread that this object happens to be.
so in effect, you are doing a loop that blocks the calling thread N times, definitely not what you intended.
in order to pause a thread, you need to have IT wait on an objet, or have it block entering a synchronized block (or use Thread.sleep(), but usually its not a good solution).
in other words, the client threads need to call wait, not the calling thread.
One addition:
it seems you are new to Java threading and synchronization, I strongly suggest that you read about it before attempting this.
Google around for some docs on the subject.
here is something to get you started:
http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html
It's not clear how the sequence of execution works.
Anyway, as already said by previous answers, calling x.wait() on a Object makes the current thread block on object x. Moreover, in order to call wait() and notify(), you first have to synchronize on that object, AND, when you call wait(), you should do it in a loop, checking for an external condition, because spurious wakeups can happen.
So, the correct pattern should be something like:
void waitForCondition() {
synchronized (lockObject) {
while (!condition) {
lockObject.wait();
}
}
}
void setCondition() {
synchronized (lockObject) {
condition = true;
lockObject.notify(); //or .notifyAll()
}
}
If you want to make the threads run one after another, try http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Exchanger.html
I didn't fully understand the concept of threads I have some questions. Assume we have the following code:
ExecCommand.java
// I don't know how this work, for now
package therads;
// Here we will have the methods and run them from the Main.java
public class ExecCommand implements Runnable
{
String name;
int time;
public ExecCommand(String s,int amount)
{
name = s;
time = amount;
}
// Run method (Runnable)
public void run()
{
try
{
// What to execute when the thread is started
System.out.printf("%s is sleeping for %d\n",name,time);
Thread.sleep(time);
System.out.printf("%s is done\n",name);
}
catch(Exception e)
{
}
}
// This dosen't work when the thread is stopped
public void stop()
{
try
{
System.out.printf("STOPPED!");
}
catch(Exception e)
{
}
}
// This dosen't work when the thread is started
public void start()
{
try
{
System.out.printf("Started!");
}
catch(Exception e)
{
}
}
}
and i call him from :
Main.java
Thread t5 = new Thread(new ExecCommand("Good Function",1000));
t5.start();
I want to println() "Started" when the thread is started and "Stopped" when it finished. It is possible?
When a thread is completed, it dies, complete released from memory? If not, how i can do that?
How can i make a thread that repeat itself like once every 1000 miliseconds till i press a key? I was thinking about while(true) { t5.start; }
but i don't know for sure.
First of all, there is no point in using the start and stop methods. Everything happens in the run method.
To print a message on start and stop, put them at the start and end of the run method. To loop indefinitely and keep executing code until an outside event happens, use a flag and loop on it:
class ThreadTask implements Runnable {
private volatile boolean flag = false;
public void setFlag(boolean value) {
flag = value;
}
public void run() {
System.out.println("Started");
while(!flag) {
// execute code
}
System.out.println("Stopped");
}
}
Then when you want the thread to stop, just set the flag to true using setFlag.
And yes, threads are automatically cleaned up by the runtime + OS after the run method terminates.
Why or when would you expect your .start() and .stop() to be called? Runnable has only a single method in the interface; .run(). The JavaDocs for Thread cover it pretty well. http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html. If you want something to happen when your Thread starts, put that something at the top of your .run(). If you want something to happen when your Thread is finishing, put it at the bottom of the .run(). By-in-large doing anything with the .start() and .stop() methods on Thread is discouraged. Concentrate on doing all you lifecycle stuff within your .run(). And get a copy of "Java Concurrency in Practice" by Goetz. It will show you the full range of your options (including don't do you own Threading directly).
You are not supposed to override the start and stop methods. They are not callback methods.
What you want is something akin to the SwingWorker class (assuming you are interested in UI related threading synchronization).
If not, you can subclass Thread yourself and provide a callback mechanism.
Yes of course. You can just print "Started" in the first line of your run() method, and print "Stopped" either in a finally section of run() method or just after t5.join()
You are not told about the details, and cannot do anything. But you can assume the resources are freed as soon as necessary. (Of course if you have reachable links for any references allocated within your thread, JVM cannot decide that these are of no use, so "complete" is not a proper word here.)
Take a look at java.util.Timer
If you prefer to use System.out.println instead of printf just change those lines of code. There's nothing thread-related about those calls.
The thread will be collected and released from memory by the garbage collector when it has stopped running and there are no live references to it. Same as all objects.
Don't override stop(). This has been deprecated and should really be dealt with by the JVM, not your application code. Just override run to implement whatever you want your thread to do, as per the docs
You can use Thread.sleep to sleep for a period of time. How accurate the sleep will be will depend on your platform and the resolution of the available system clock.