java - Why is my waiting thread not waking up even though it's being notified? -
i have client server tic-tac-toe game attempting run different thread (in different terminals) each player, have built in eclipse.
my goal make each player make move, .notify() other player , .wait() other player make move, , alternate process until game done.
tosync object used synchronization
public static final object tosync = new object() and found in player class (which extended both xplayer , oplayer).
the lines seem causing problem commented in xplayer , oplayer:
both xplayer , oplayer have main methods, can run concurrently. x makes first move uses socket communicate move server.
server passes move o, makes own move , passes server. alternates until game done.
making first move x player works fine, once intial move made, o supposed display board , prompt user move. not happen: x makes move, , o supposedly notified, in fact never wakes up. curly brace ending while loop commented in oplayer never reached (which know true debugging i've done far).
class xplayer:
import java.io.*; public class xplayer extends player implements runnable { public static volatile boolean xturn = true; public xplayer() throws ioexception { super(); mark = letter_x; } public void run() { try { system.out.println("okay " + name + ", x-player"); synchronized(tosync) { cell move = makemove(); out.println(move.tostring()); board.addmark (move.row(),move.col(),move.mark()); board.display(); xturn = false; tosync.notifyall(); //this line isnt working!! system.out.println(waiting); } synchronized(tosync) { while (!xturn) {tosync.wait();} } while (!board.isover()) { synchronized(tosync) { string line; {line = in.readline();} while (line == null); cell opponentmove = cell.split(line); board.addmark (opponentmove.row(),opponentmove.col(), opponentmove.mark()); string move = makemove().tostring(); out.println(move); xturn = false; tosync.notifyall(); while (!xturn) {tosync.wait();} } } endgame(); sock.close(); in.close(); stdin.close(); out.close(); } catch (interruptedexception ie) { system.out.println("ie in xplayer! " + ie.getmessage()); system.exit(1); } catch (ioexception ioe) { system.out.println("ioe in xplayer! " + ioe.getmessage()); system.exit(1); } } public static void main(string[] args) { try { xplayer x = new xplayer(); thread t = new thread(x); t.start(); } catch(ioexception ioe) { system.err.println ("ioe in xplayer main " + ioe.getmessage()); system.exit(1); } } class oplayer:
import java.io.*; public class oplayer extends player implements runnable { public oplayer() throws ioexception { super(); mark = letter_o; } public void run() { try { synchronized(tosync) { system.out.println("okay " + name + ", o-player"); system.out.println(waiting); while(!xplayer.xturn) {tosync.wait();} // line isn't waking while (!board.isover()) { string line; {line = in.readline();} while (line == null); cell opponentmove = cell.split(line); board.addmark (opponentmove.row(),opponentmove.col(),opponentmove.mark()); cell move = makemove(); out.println(move.tostring()); board.addmark(move.row(),move.col(),move.mark()); board.display(); xplayer.xturn = true; tosync.notifyall(); system.out.println(waiting); while (xplayer.xturn) {tosync.wait();} } } endgame(); sock.close(); in.close(); stdin.close(); out.close(); } catch (interruptedexception ie) { system.out.println("ie in oplayer " + ie.getmessage()); system.exit(1); } catch (ioexception ioe) { system.err.println("ioe in oplayer " + ioe.getmessage()); system.exit(1); } } public static void main(string[] args) { try { oplayer o = new oplayer(); thread t = new thread(o); t.start(); } catch(ioexception ioe) { system.err.println("ioe in oplayer main" + ioe.getmessage()); system.exit(1); } } } as indicated code, tosync.notifyall() call in xplayer not waking oplayer thread, , stuck in deadlock once first move has been made xplayer
i believe 2 classes needed resolve problem in case, here classes player board , tttserver: class player:
import java.net.*; import java.io.*; public class player implements constants { protected static final object tosync = new object(); protected socket sock; protected bufferedreader stdin; protected bufferedreader in; protected printwriter out; protected string name; protected char mark; protected board board; public player() throws ioexception { sock = new socket("localhost",1298); stdin = new bufferedreader(new inputstreamreader(system.in)); in = new bufferedreader(new inputstreamreader(sock.getinputstream())); out = new printwriter(sock.getoutputstream(),true); system.out.println(welcome); system.out.println("please enter name:"); name = stdin.readline(); board = new board(); } public cell makemove() throws ioexception { board.display(); int row = -1; int col = -1; { while (row < 0 || row > 2) { system.out.println (name + ", row next move in?"); row = integer.parseint(stdin.readline()); if (row < 0 || row > 2) {system.out.println("invalid entry! try again...");} } while (col < 0 || col > 2) { system.out.println (name + ", column next move in?"); col = integer.parseint(stdin.readline()); if (col < 0 || col > 2) {system.out.println("invalid entry! try again...");} } if (board.getmark(row, col) != space_char) {system.out.println("that spot taken try again...");} } while (board.getmark(row,col) != space_char); return new cell(row,col,mark); } public void endgame() { if (board.xwins() == 1) {system.out.println(end + xwin);} if (board.owins() == 1) {system.out.println(end + owin);} else {system.out.println(end + " tie!!");} } } class tttserver:
import java.net.*; import java.io.*; public class tttserver implements constants { public static void main(string[] args) { try { serversocket ss = new serversocket(1298,2); system.out.println("the server running..."); socket sock; board board = new board(); sock = ss.accept(); sock = ss.accept(); bufferedreader in = new bufferedreader(new inputstreamreader(sock.getinputstream())); printwriter out = new printwriter(sock.getoutputstream(),true); { string movestring; {movestring = in.readline();} while (movestring == null); cell move = cell.split(movestring); board.addmark(move.row(), move.col(), move.mark()); out.println(movestring); } while(!board.isover()); in.close(); out.close(); ss.close(); sock.close(); } catch(ioexception ioe) { system.out.println("ioe in tttserver " + ioe.getmessage()); system.exit(1); } } } class board:
public class board implements constants { /** * 2d char array stores game board , * total number of marks */ private char theboard[][]; private int markcount; /** * default constructor initializes array , fills * space_chars constants interface */ public board() { markcount = 0; theboard = new char[3][]; (int = 0; < 3; i++) { theboard[i] = new char[3]; (int j = 0; j < 3; j++) theboard[i][j] = space_char; } } /** * getter mark @ location specified arguments * * @param row * @param column * * @return mark */ public char getmark(int row, int col) {return theboard[row][col];} /** * getter number of moves have been made far * * @return markcount */ public int getmarkcount() {return markcount;} /** * @return true if game over, otherwise false */ public boolean isover() { if (xwins() == 1 || owins() == 1 || isfull()) {return true;} return false; } /** * @return true if board has been filled * x_chars , o_chars constants interface, else false */ public boolean isfull() {return markcount == 9;} /** * runs checkwinner on letter_x constants interface * * @return true if x has won, else false */ public int xwins() {return checkwinner(letter_x);} /** * runs checkwinner on letter_o constants interface * * @return true if o has won, else false */ public int owins() {return checkwinner(letter_o);} /** * uses formatting helper methods display board * in console */ public void display() { displaycolumnheaders(); addhyphens(); (int row = 0; row < 3; row++) { addspaces(); system.out.print(" row " + row + ' '); (int col = 0; col < 3; col++) system.out.print("| " + getmark(row, col) + " "); system.out.println("|"); addspaces(); addhyphens(); } } /** * add mark in last argument location specified * first 2 arguments * * @param row * @param column * @param mark */ public void addmark(int row, int col, char mark) { theboard[row][col] = mark; markcount++; } /** * clears board replacing marks * space_chars constants interface */ public void clear() { (int = 0; < 3; i++) (int j = 0; j < 3; j++) theboard[i][j] = space_char; markcount = 0; } /** * checks if player argument mark has won game * * @param mark * * @return true if game won, else false */ int checkwinner(char mark) { int row, col; int result = 0; (row = 0; result == 0 && row < 3; row++) { int row_result = 1; (col = 0; row_result == 1 && col < 3; col++) if (theboard[row][col] != mark) row_result = 0; if (row_result != 0) result = 1; } (col = 0; result == 0 && col < 3; col++) { int col_result = 1; (row = 0; col_result != 0 && row < 3; row++) if (theboard[row][col] != mark) col_result = 0; if (col_result != 0) result = 1; } if (result == 0) { int diag1result = 1; (row = 0; diag1result != 0 && row < 3; row++) if (theboard[row][row] != mark) diag1result = 0; if (diag1result != 0) result = 1; } if (result == 0) { int diag2result = 1; (row = 0; diag2result != 0 && row < 3; row++) if (theboard[row][3 - 1 - row] != mark) diag2result = 0; if (diag2result != 0) result = 1; } return result; } /** * final 3 helper methods called display * format board in console */ void displaycolumnheaders() { system.out.print(" "); (int j = 0; j < 3; j++) system.out.print("|col " + j); system.out.println(); } void addhyphens() { system.out.print(" "); (int j = 0; j < 3; j++) system.out.print("+-----"); system.out.println("+"); } void addspaces() { system.out.print(" "); (int j = 0; j < 3; j++) system.out.print("| "); system.out.println("|"); } }
here's mistake:
both xplayer , oplayer have main methods, can run concurrently.
if you're running 2 main() methods, they're not running "concurrently"; they're entirely separate processes. means no shared threads, variables, objects, notifications etc. if want share state, need start single main() method:
class starterclass { public static void main(string[] args) { // start xplayer thread try { xplayer x = new xplayer(); thread t = new thread(x); t.start(); } catch(ioexception ioe) { system.err.println ("ioe in xplayer main " + ioe.getmessage()); system.exit(1); } // start oplayer thread try { oplayer o = new oplayer(); thread t = new thread(o); t.start(); } catch(ioexception ioe) { system.err.println("ioe in oplayer main" + ioe.getmessage()); system.exit(1); } } } if intent have each player run separate client while alternating turns, thread synchronization wrong tool job. you'll need implement custom messaging between server , clients keep them in sync.
Comments
Post a Comment