具有计时器,单线程执行器和阻塞的Java多线程环境。非期望的输出

时间:2016-02-16 01:30:22

标签: java multithreading synchronization timertask scheduledexecutorservice

public static void main(String[] args) throws Exception {
...
        Runnable blackjackThread = BLACKJACK;
        ScheduledExecutorService blackjackThreadService = Executors.newSingleThreadScheduledExecutor();
        blackjackThreadService.scheduleAtFixedRate(blackjackThread, 10, 30, TimeUnit.SECONDS);
...
}

这是服务类运行方法。

private TimerTask initialWaitToJoinGameTask;
private int counter = 0;
private Timer timer;
private Message message = new Message();
protected AtomicBoolean startGame = new AtomicBoolean();
protected AtomicBoolean waitToStartRound = new AtomicBoolean();
protected int duration = 10;

public synchronized void run() {
        doRoundTimer(duration);
        waitToStartRound.set(true);
        Deck deck = new Deck();
        deck.shuffleDeck();

        message.globalMessage("GAMBLE", "A new game of " + AnsiTable.getCode("yellow") + "Blackjack " + AnsiTable.getCode("white") + "is starting!! #ursa BLACKJACK");
        timer.scheduleAtFixedRate(initialWaitToJoinGameTask, 30, 1000);

        while (!waitToStartRound.get()) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
            for (User u : inRoom) {
                inRoom.remove(u);
                inGame.add(u);
                inGamePlayers.add(new Player(u));
            }
        }

        do {
            message.gameMessage(inRoom, "This round of " + AnsiTable.getCode("yellow") + "Blackjack " + AnsiTable.getCode("white") + "has begun.");

            for (Player p : inGamePlayers) {
                p.addCardToHand(deck.nextCard());
                message.gameMessage(inGame, p.user.getLoginName() + " recieved " + p.lastCardGiven().getCardValue() + " of " + p.lastCardGiven().getSuit());
            }

            for (Player p : inGamePlayers) {
                p.addCardToHand(deck.nextCard());
                message.gameMessage(inGame, p.user.getLoginName() + " recieved " + p.lastCardGiven().getCardValue() + " of " + p.lastCardGiven().getSuit());
            }

            startGame.set(false);
        } while (startGame.get());

        for (User u : inGame) {
            inGame.remove();
            inRoom.add(u);
        }

        for (Player p : inGamePlayers) {
            inGamePlayers.remove(p);
        }

        message.gameMessage(inRoom, "Another round of " + AnsiTable.getCode("yellow") + "Blackjack " + AnsiTable.getCode("white") + "will begin shortly!");
    }
}

最后这是计时器任务。

public synchronized void doRoundTimer(int dur) {
    initialWaitToJoinGameTask = new TimerTask() {
        @Override
        public synchronized void run() {
            counter++;
            if (counter >= dur) {
                counter = 0;
                timer.cancel();
                waitToStartRound.set(false);
                startGame.set(true);
                notifyAll();
            }
        }
    };
    timer = new Timer("WaitTimer");
}

所以应该发生的是单线程服务启动,启动一个受保护的块计数器,该计数器由持续时间为秒的计时器任务递增。之后它应该为每个玩家发2张牌然后退出startGame循环。在此之后,它应当以固定速率安排当前线程,等待30秒,然后重新启动另一个线程。

然而,正在发生的是

07:28 PM << Gamble >> A new game of Blackjack is starting!! #ursa BLACKJACK
07:28 PM << Gamble >> This round of Blackjack has begun.
07:28 PM << Gamble >> Another round of Blackjack will begin shortly!
07:29 PM << Gamble >> A new game of Blackjack is starting!! #ursa BLACKJACK
07:29 PM << Gamble >> This round of Blackjack has begun.
07:29 PM << Gamble >> Another round of Blackjack will begin shortly!

在线程开始和游戏开始之间,实际上没有发生任何卡片交易,也没有持续时间等待时间。

0 个答案:

没有答案