Concurrency issue in Java - java

I have a concurrency problem in Java that i'm to able to solve.
I want to set a timeout for a player to write an input and when it's turn is over I set a flag (player.myTurn) to false in another thread, which control the game logic, cause I want this thread to stay in the second while and set the timeout to infinity not to catching the SocketTimeoutException.
The problem is that after sending the command to the controllerServerSide on the last player input, this thread comes back to inputStream.readObject() before the variable myTurn is modified by the other Thread, so it set again the timeout, and this is a problem for the game.
How can I make this thread to wait until myTurn is changed (only over the last player input)?
ServerThread
public void run(){
while(!isStopped){
try {
while(!player.getMyTurn()){
socket.setSoTimeout(0);
}
socket.setSoTimeout(INPUT_TIMEOUT);
//ServerThread arrives here 'cause myTurn it isn't changed yet
String command = (String) inputStream.readObject();
socket.setSoTimeout(0);
controllerServerSide.receiveCommand(command);
}catch (IOException e) {}
GameThread
for(Player player : playerList){
if(!player.getConnectionState()){
player.setMyTurn(true);
//here it starts his turn
winner = turn.executeTurn(player);
//here it finish his turn
player.setMyTurn(false);
if(winner != null){
playerList.remove(winner);
break;
}
}
}
I'm sorry if this is a bad coding style, but I'm practically new to Java.
Thanks for your answers!

Related

Implementing a simple turn-based game in Java using the wait-notify approach

I'm trying to implement a word game in Java, where each player takes turns extracting a number of random letters from a set, then trying to create a valid word with those letters. This is what I have so far (simplified for clarity's sake):
In the Game class, I start the game by running a thread for each player (and one for the timekeeper). I want the first player in the activePlayers list (which initially is the same as the players list) to make the first move, so I initialized the turn and turnIndex attributes to correspond to this player:
public void play()
{
this.turn = activePlayers.get(0); //the player who joined first goes first
this.turnIndex = 0; //the player's index in the ArrayList
for(Player player : players) {
new Thread(player).start();
}
new Thread(new Timekeeper()).start(); //keeps track of the game's duration
}
In the Player class, I want the players on stand-by to not do anything, and simply wait for the current player to finish their business, hence the first while loop. Then, when a player's turn has ended, I want that thread to yield the monitor to another player's thread and wait its next turn. This is how I decided to approach it:
private synchronized boolean submitWord() throws InterruptedException
{
while(game.turn != this)
{
System.out.println(this.name + " is waiting their turn...");
wait();
}
Thread.sleep(1000);
List<Tile> extracted = game.getBag().extractTiles(wordLength);
if(extracted.isEmpty())
return false; //if there are no more letters to extract, the thread ends its execution
//game logic goes here - creating and validating the word
//after this player is done, the next player makes their move
game.turnIndex++;
if(game.turnIndex >= game.activePlayers.size())
game.turnIndex = 0;
game.turn = game.activePlayers.get(game.turnIndex);
notifyAll();
return true;
}
#Override
public void run()
{
do {
try {
this.running = this.submitWord();
} catch(InterruptedException e) {
System.out.println("Something went wrong with " + this.name + "...");
e.printStackTrace();
}
} while(this.running);
game.activePlayers.remove(this); //the player is now inactive
if(game.winner == this)
System.out.println("Winner: " + this.name + " [" + this.score + " points]");
}
However, when I try to run the program, I get something like this:
Player 2 is waiting their turn...
Player 3 is waiting their turn...
1 seconds elapsed...
Player 1: AERIAL [36 points]
Player 1 is waiting their turn...
2 seconds elapsed...
3 seconds elapsed...
4 seconds elapsed...
5 seconds elapsed...
6 seconds elapsed...
Basically, the game doesn't move past Player 1's first try, and I get stuck in an infinite loop where nothing happens. Am I not using the wait() and notifyAll() methods properly? How should I make the player threads communicate with each other?
If I have understood your code correctly, that submitWord method belongs to the Player class. The keyword synchronized should be used to obtain the monitor of a shared resource to limit different threads from accessing the same resource at the same time and avoid race conditions.
In your case, you're synchronizing over a Player thread which is not the right design. You should synchronize instead over the shared resource which is the game object in this scenario. Besides, try to use synchronized blocks rather than entire synchronized methods, as the latter are more likely to block.
Within the Player's run method you should check whether the thread can acquire the game resource first with a synchronized block, if they do, then you can check whether it's the Player's turn by confronting the turn index of the game object with the Player's index. If it's not the Player's turn it invokes the wait() method; otherwise it carries on with its task by invoking submitWord.
Here, I've tweaked your code. You forgot a notify (or notifyAll) call when you were returning false in your submitWord method. That might have caused some stuck scenarios when there were no combinations available.
//Now, this method can be called only under the condition the the game's monitor lock has been already acquired. So, it can only be invoked within a synchronized block.
private boolean submitWord() {
List<Tile> extracted = game.getBag().extractTiles(wordLength);
if(extracted.isEmpty()){
//notify is more efficient than notifyAll as it causes less overhead by awakening only one random thread instead of all the ones waiting
this.game.notify();
//you were returning without notifying here... This might have caused some stucking scenarios...
return false;
}
//game logic goes here - creating and validating the word
//Rotating the turn
game.turnIndex = (this.game.turnIndex + 1) % this.game.activePlayers.size();
game.turn = game.activePlayers.get(game.turnIndex);
this.game.notify();
return true;
}
#Override
public void run() {
do {
synchronized(this.game){
if (this.game.indexTurn == this.index){
this.running = this.submitWord();
//It's more efficient to check here whether the player must be removed or not as you already own the game's lock
if (!this.running){
this.game.activePlayers.remove(this);
}
} else {
try {
this.game.wait();
} catch(InterruptedException e) {
System.out.println("Something went wrong with " + this.name + "...");
e.printStackTrace();
}
}
}
} while(this.running);
//you should re-acquire the game's lock here since you're modifying the set of players
//synchronized(this.game){
// this.game.activePlayers.remove(this);
//}
if(this.game.winner == this){
System.out.println("Winner: " + this.name + " [" + this.score + " points]");
}
}
Just a thought, but it could be that the sleep is happening within a synchronized method: Thread.sleep is blocking other thread also, working on other method, along with itself callled inside synchronized method

Timer issues in java when using Timeout Exceptions, code doesn't run correctly after a Timeout Exception

I'm designing a game in java called that's similar to the board game go. In the implementation there is also a mode called speed mode, where if a player doesn't take a turn within the time limit (5 seconds) the other player is to win. This mode can also be won normally be "capturing" the opposition piece. After either of these conditions is met , the game is to be ran again from the main menu. This works fine in normal mode and in speed mode when the win conditions are met by capturing. When it's won by time running out however it behaves very oddly, almost randomly prompting for input and printing.
The code for the time is as follows:
public Boolean speedMode(Player player, Player opponent) {
ExecutorService service = Executors.newSingleThreadExecutor();
try {
Runnable r = new Runnable() {
Boolean outOfRange;
public void run() {
do {
outOfRange = takeTurn(player);
} while (outOfRange == true);
}
};
Future<?> f = service.submit(r);
f.get(5, TimeUnit.SECONDS);
} catch (final InterruptedException e) {
System.out.println("The thread was interrupted during sleep, wait or join");
} catch (final TimeoutException e) {
player.setWon(false);
System.out.println("\n" + player.getName() +", you took too long... ");
return true;
} catch (final ExecutionException e) {
System.out.println("An exception from within the Runnable task");
}
return false;
}
When the TimeoutException happens the oppisite player wins while loop shown beow is exited and the correct congratulations are printed. The problem is when It starts the new game at the bottom line of code thats when the weird behaviour starts. Is there something I need to close perhaps in the timer method?It's almost like it's still running in the back ground.
else {
do {
timeOut = speedMode(second, first);
if(winCheck1(first) == true || timeOut == true){
break;
}
timeOut = speedMode(first, second);
} while (winCheck1(second) != true && timeOut != true);
if(player1.isWon() == true){
System.out.println("\n\nCongratulations " + player1.getName() + " you are the winner!\n\n");
}
else{
System.out.println("\n\nCongratulations " + player2.getName() + " you are the winner!\n\n");
}
}
//reload the menu
Game game = new Game();
}
Basically my question is; can anyone tell me why starting a new game does not work correctly after throwing a TimeoutException?
Is there something I need to close perhaps in the timer method?It's almost like it's still running in the back ground.
If you don't call shutdown on the executor the worker thread that the executor created will hang around. (This is independent of the scope in which you declared the executor.) If it is a non-daemon thread then it will keep the old JVM alive.
Also your task needs to be responsive to interruption. See the documentation for shutdownNow:
There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate.
"Responding to interrupts" means checking Thread.currentThread().isInterrupted() to see if the thread has been canceled and then acting on it (finding a stopping place, doing cleanup, and exiting the run method), and restoring the interrupted flag (Thread.currentThread().interrupt()) if an InterruptedException or InterruptedIOException is caught.

Thread, while loop and a System.out.print statement

Hi guys I have a nested Thread and using it to see when a player has taken a turn (in a draughts game) O have a game object and a public variable changedTurns.
new Thread() {
public void run(){
check();
}
private void check(){
boolean sent = false;
while(true){
System.out.println("ee"); \\line 9
if(game.changedTurns){
System.out.println("gg");
if(!sent){
System.out.println("ok");
sent =true;
}
}
}
}.start();
Everything works as expected like above I.e console shows plenty of "ee" followed by "gg" and then "ok" when the player takes their turn, however without line 9 nothing is shown when the player takes their turn ?!
You don't need to use threading to analyze whether the player has taken a turn. Just create a Player[] array and add a variable turn for the index of the player whose turn it is. Increment turn when a Player makes a turn.

Java thread timing issue in my card game server

I have a timing issue and I don't know how to fix it.
In my second loop, Display card, it loops and each connection starts a class called cLookAtCardConnection. This class will sometimes set the flag mPlayerList.GetNextFlag(), thus causing the loop to exit and the program goes to the first loop, Turn card over, which calls the class cLookAtCardConnection
The problem is that after mPlayerList.GetNextFlag() is set, the next couple connections are still in the same loop and call the class cLookAtCardConnection instead of (exiting?) the loop when the flag is set and going into the loop that calls cLookAtCardConnection.
Why is there a delay in the loop exiting after the flag has been set?
while( lBoard.Next()==true)
{
mPlayerList.Next();
// inner loop wait for all players
/////////////////////////////////////////////////////////////////////////////
// turn one card over
mPlayerList.WaitForAllPlayers();
do
{
do{
r=GetClient();
switch(r)
{
case 0: return; // exitvon a very bad error
}
} while(r==2);// loop if it was a timeout
cTurnCardOvrerConnection thread = new cLookAtCardConnection("thread3", connection, mPlayerList, mPlayersMessages, lBoard);
} while( mPlayerList.AllPlayersFinished()==false);// end while
//////////////////////////////////////////////////////////////////////////
// Display card -LOOK AT CARD
mPlayerList.ClearNextFlag();
mPlayerList.WaitForAllPlayers();
do
{
System.out.println(Thread.currentThread()+": Display card \r");
do{
r=GetClient();
switch(r)
{
case 0: return; // exitvon a very bad error
}
} while(r==2);// loop if it was a timeout
cLookAtCardConnection thread = new cLookAtCardConnection("thread3", connection, mPlayerList, mPlayersMessages, lBoard);
// after this flag is set the next couple connectons are still in this loop???
} while( mPlayerList.GetNextFlag()==false);// end while
} // reloop game board
} // loop forever
// System.out.println("--------- Eit player loop ------------------- \r");
} catch(IOException ec)
{
System.out.println(ec.getMessage());
}
} // end run
} // end of class
You probably need to set up a synchronized block so that the code inside the do-while loop is only accessible to a single thread at a time.

Progress bar increment by 1 every 100th of second

I'm trying to get a JProgressBar to increment by 1 every 100th of a second, and at the moment I'm using Thread.sleep(100) inside a while statement like so:
try {
while (i<=100){
doTime();
}
} catch (InterruptedException ex) {
Logger.getLogger(SplashScreen.class.getName()).log(Level.SEVERE, null, ex);
}
public void doTime() throws InterruptedException{
jLabel1.setText("sleeping");
Thread.sleep(100);
jLabel1.setText("start");
i++;
pb.setValue(i);
pb.repaint();
}
and If I debug by doing a System.out.println it displays in real time but the swing GUI freezes until it drops out of the while loop can anyone help?
thanks
matt
As derivation said, you should use SwingWorker. From its javadoc:
"SwingWorker is designed for situations where you need to have a long running task run in a background thread and provide updates to the UI either when done, or while processing. Subclasses of SwingWorker must implement the doInBackground() method to perform the background computation."
With this slight change to ProgressBarDemo.java in the java tutorial, you almost get what you want.
public Void doInBackground() {
Random random = new Random();
int progress = 0;
//Initialize progress property.
setProgress(0);
while (progress < 100) {
//Sleep for up to one second.
try {
//original code: Thread.sleep(random.nextInt(1000));
Thread.sleep(10);
} catch (InterruptedException ignore) {}
//Make random progress.
//originalcode: progress += random.nextInt(10);
progress++;
setProgress(Math.min(progress, 100));
}
return null;
}
The problem is that you are sleeping the Swing Event thread. You'll want to create a new thread for running the loop, and then have that loop update the progressbar on the swing event thread.
I would use the Swing Worker thread for the loop. Then use invokeLater for updating the progressbar.
Another good swing/thread tutorial.
Besides what derivation said, you are sleeping for 100 milliseconds. That means you are only updating every tenth of a second, not every hundredth.
If doTime() is being called within the Event Dispatch Thread (EDT), which it should since it is calling UI code (jLabel1.setText() and others), then it should not be calling sleep() at all. You do not want to freeze your UI.
The correct way of doing this is to use a timer to wake up in the correct moments (say, every 10 ms) and update the progress. The code by Jala is also a good answer, and it is the official Swing Way of doing things (timers are lower level than SwingWorkers).

Categories