此处用一个两人的井字游戏,又叫tic tac toe游戏为例说明使用方法
采用c/s模式,socket编程,服务器端要对两个进程(两个player)进行顺序协调,交替下棋
1.定义一个private Lock gameLock;
gameLock = new ReentrantLock(); //
新建一个锁
// condition variable for both players being connected
//两个player连接服务器的条件变量
otherPlayerConnected = gameLock.newCondition();
// condition variable for the other player's turn
//控制玩家顺序的条件变量
otherPlayerTurn = gameLock.newCondition();
2.下面的代码展示了如何用gameLock和otherPlayerConnected条件变量
条件变量必须放在gameLock.lock()和gameLock.unlock()之间
runGame= Executors.newFixedThreadPool( 2 );//定义了一个可以容纳两个线程的线程池
public voidexecute()
{
// wait for each client to connect
for ( int i = 0; i < players.length; i++ )
{
try // wait for connection, create Player, start runnable
{
players[ i ] = new Player( server.accept(), i );
runGame.execute( players[ i ] ); // execute player runnable
} // end try
catch ( IOException ioException )
{
ioException.printStackTrace();
System.exit( 1 );
} // end catch
} // end for
//执行完for循环有两个线程在跑
gameLock.lock(); // lock game tosignal player X's thread
try
{
players[ PLAYER_X ].setSuspended( false ); // resume playerX参见3中的player的run方法蓝色部分,玩家PLAYER_X将suspend变量设为false,则他的进程将等待signal或者中断来到才继续执行。
otherPlayerConnected.signal();//条件变量发出的signal将唤醒X的进程
} // end try
finally
{
gameLock.unlock();// unlock game after signalling player X
} // end finally
} // end method execute
3.player是server的内类,实现了Runnable接口
private
class Player implements Runnable
publicvoid run()
{
// send client its mark (X or O), process messages fromclient
try
{
displayMessage( "Player " + mark + " connected\n" );
output.format( "%s\n", mark ); // send player's mark
output.flush(); // flush output
// if player X, wait for another player to arrive
if ( playerNumber == PLAYER_X )
{
output.format( "%s\n%s", "Player X connected",
"Waiting for another player\n" );
output.flush(); // flush output
gameLock.lock(); // lock game to
wait for secondplayer
try
{
while( suspended )
{
otherPlayerConnected.await(); // wait for player O
} // endwhile
} // end try
catch ( InterruptedException exception )
{
exception.printStackTrace();
} // end catch
finally
{
gameLock.unlock(); // unlock game after second player
} // end finally
// send message that other player connected
output.format( "Other player connected. Your move.\n" );
output.flush(); // flush output
} // end if
else
{
output.format( "Player O connected, please wait\n" );
output.flush(); // flush output
} // end else
// while game not over
while ( !isGameOver() )
{
int location = 0; // initialize move location
if ( input.hasNext() )
location = input.nextInt(); // get move location
// check for valid move
if (
validateAndMove( location, playerNumber) )
{
displayMessage( "\nlocation: " + location);
output.format( "Valid move.\n" ); // notify client
//if(check(board));
// output.format("You have succeed");
output.flush(); // flush output
} // end if
else // move was invalid
{
output.format( "Invalid move, try again\n" );
output.flush(); // flush output
} // end else
} // end while
} // end try
finally
{
try
{
connection.close(); // close connection to client
} // end try
catch ( IOException ioException )
{
ioException.printStackTrace();
System.exit( 1 );
} // end catch
} // end finally
} // end method run
4.如何用otherPlayerTurn条件变量控制线程执行顺序
validateAndMove在3中run方法中调用,验证执行顺序是否合理
publicboolean validateAndMove( int location, int player )
{
// while not current player, must wait for turn
//如果进程不是当前进程,那边必须等待当前进程执行完毕后
otherPlayerTurn.signal();
while ( player != currentPlayer )
{
gameLock.lock(); // lock game to waitfor other player to go
try
{
otherPlayerTurn.await(); // wait forplayer's turn
} // end try
catch ( InterruptedException exception )
{
exception.printStackTrace();
} // end catch
finally
{
gameLock.unlock(); // unlock gameafter waiting
} // end finally
} // end while
// if location not occupied, make move
if ( !isOccupied( location ) )
{
board[ location ] = MARKS[ currentPlayer ]; // set move onboard
currentPlayer = ( currentPlayer + 1 ) % 2; // change player
// let new current player know that move occurred
players[ currentPlayer ].otherPlayerMoved( location );
gameLock.lock(); // lock game tosignal other player to go
try
{
otherPlayerTurn.signal(); // signalother player to continue
} // end try
finally
{
gameLock.unlock(); // unlock gameafter signaling
} // end finally
return true; // notify player that move was valid
} // end if
else // move was not valid
return false; // notify player that move was invalid
} // end methodvalidateAndMove