2

I was wondering if someone coule help me on how to implement a thread which runs infinitely in the background until the user presses p at which point it pauses the other threads and upon pressing r resumes other threads. This is some of the code

Some of the main object

public class CardGame
{
   static Player[] players;
   static int handSize;
   static Queue<Card>[] playingDeckArray;


public static void main(String[] args){
        Scanner reader = new Scanner(System.in);

        System.out.println( "\nHello, how many players would you like" );
        int playersNum = Integer.parseInt(Checks.userInputCheck( "\\d" ));
        System.out.println( "\nHow many cards should each player begin with" );
        int handSize = Integer.parseInt(Checks.userInputCheck( "\\d" ));
        System.out.println( "\nWhich strategy would you like to use 1 or 2" );
        int strategy = Integer.parseInt(Checks.userInputCheck( "[12]$" ));

        Logger.createDeck( playersNum, handSize );

        makePlayers( playersNum, handSize, strategy );

        makePlayingDecks( playersNum );

        dealInitialHand( playersNum, players, handSize );

        makePlayerOutputs();

        for ( int i = 0; i < players.length; i++){
           logInitialHand(players[i]);
        }

        CardGame cG = new CardGame();
        cG.startPauseThread();

        for ( int i = 0; i < players.length; i++){
            new Thread(players[i]).start();
        }
   }

   public void startPauseThread(){
   Thread add = new Thread( pauseInputThread );
   add.start();
}


Thread pauseInputThread = new Thread(){
       public void run(){ 
         int i = 0;
         for(;;){
             System.out.println("i'm still here" );
             Scanner reader = new Scanner(System.in);
             String result = Checks.userInputCheck( "[pPrR]$" );
             i++;
             System.out.println(i);
            }
       }
};
}

The player object which are the threads to be paused

public class Player implements Runnable
{
    Card[] hand;
    String playerName;
    int strategyChosen;

    public void run(){
        System.out.println( "les do dis" );
    }

    private Player(){
    }

    public Player( int strategy, int cardsInHand, int playerNumber ){
        hand = new Card[cardsInHand];
        strategyChosen = strategy;
        playerName = "Player " + playerNumber;
    }

    public String getPlayerName(){
        return playerName;
    }

    public void fillHand(){
       for ( int i = 0; i < hand.length; i++){
            hand[i] = new Card(0);
       }
    }

    public void setHand( int value, int index ){
        hand[index].setCardValue( value );
    }

    public void seeHand(){
        for ( int i = 0; i < hand.length; i++){
            System.out.println( hand[i].getCardValue() );
        }
    }

    public String getHand(){
        String result = "";
        for ( int i = 0; i < hand.length; i++ ){
            result = result +  hand[i].getCardValue() + " \n" ;
        } 
        return result;
    }

    public int getHandValue( Card card ){
        return card.getCardValue();
    }

}

The players will be 'playing a game' where they draw and discard objects from arrays, but the user should be able to pause and resume the programm at any point during the game. i just dont quite understand how to go about that, using events and listners.

Help would be appreciated. Thank you.

3
  • 1
    What action makes that game advance a step? Just don't do that and the game is "paused". Sidenote: why do you need threads at all? Your players don't play in paralled, their actions happen in sequence. Commented Dec 7, 2013 at 16:44
  • 2
    The player thread doesn't do anything other than printing a sungle string. there's nothing to be paused. But to answer your question: a thread can't be paused from the outside. It needs to decide to pause itself. Commented Dec 7, 2013 at 16:47
  • apologies I havent haven't fully figured out the game steps, but the player threads will be independantly take and adding items to arrays until someone wins, and I was just wondering how if I could pause/ put to sleep the threads upon user input and how to sort of go about that. Commented Dec 7, 2013 at 16:51

2 Answers 2

6

Thread has no mechanism for this on its own. You can, however, easily add this functionality in to your own process. You'll have some flag to set and check and then probably the best is to have a wait/notify scheme. Here's a simple demonstration:

abstract class PausableTask implements Runnable {
    private volatile boolean paused;
    private final Object lock = new Object();

    void setPaused(boolean shouldPause) {
        synchronized (lock) {
            paused = shouldPause;
            if (!paused) {
                lock.notify();
            }
        }
    }

    boolean isPaused() { return paused; }

    @Override
    public void run() {

        for (;;) {                
            synchronized (lock) {
                while (paused) {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {}
                }
            }

            doTask();
        }
    }

    abstract void doTask();
}

class Counter {
    volatile long count;

    public static void main(String[] args) {
        final Counter counter = new Counter();

        PausableTask increment = new PausableTask() {
            @Override
            void doTask() {
                counter.count++;
            }
        };

        PausableTask decrement = new PausableTask() {
            @Override
            void doTask() {
                counter.count--;
            }
        };

        decrement.setPaused(true);
        PausableTask next = increment;

        Scanner in = new Scanner(System.in);
        long count = counter.count;

        new Thread(increment).start();
        new Thread(decrement).start();

        for (;;) {
            System.out.print(
                (next == increment ? "Counting up from " : "Counting down from ")
                + count + ". Enter 'exit' to abort or anything else to toggle: "
            );

            if (in.nextLine().equals("exit")) {
                System.exit(0);
            }

            if (increment.isPaused()) {
                next = increment;
                decrement.setPaused(true);
            } else {
                next = decrement;
                increment.setPaused(true);
            }

            count = counter.count;
            next.setPaused(false);
        }
    }
}

For taking user input from the keyboard, there's not really a convenient way to do that in Java. If you want to take straight keystrokes you need a GUI component for them to happen in. If you do plan on implementing a GUI take a look at the key bindings tutorial.

Sign up to request clarification or add additional context in comments.

1 Comment

I would use the ReentrantLock instead of synchronized(this) and a lock object. But this code works as well +1.
2

It's not possible to pause a thread simply by calling some predefined method, nor it's possible to kill a thread. The only thing you can do is to implement this behavior by yourself. It means that you will do something like this:

public class MyThread extends Thread {
    private volatile boolean running = true;
    private volatile boolean paused  = false;

    public void kill() {
        this.running = false;
    }

    public void setPaused(boolean paused) {
        this.paused = paused;
    }

    @Override
    public void run() {
        while (running) {
            if (!paused) {
                // do another step
            }
        }
    }
}

However, it's possible that I didn't understand your question correctly. Leave me a feedback so I can update my answer eventually.

6 Comments

no, this is useful i just wasn't sure about how to make the thread that runs in the background waiting for the user to pause and how to communicate the pause to the other threads but this is helpful. Thank you.
That won't work correctly. The boolean variables must be volatile or be of type AtomicBoolean to work fine. And it will also make the thread go into a busy loop consuming all the CPU when paused, instead of sitting idle until woken up. So, the answer is correct, but the example code is not.
The main part i cant fiugre out is how to make the threads on user input, would i need to create a keylisterner method, which would somehow notify the othre threads to pause.
A KeyListener is for AWT/Swing applications, not for console-based applications.
oh, then how would I go about implementing that, my code has a thread which should run infinitely in the back ground waiting for user response but doesnt when i run the program.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.