簡體   English   中英

如何暫停/恢復Java線程

[英]How to pause / resume Java Threads

我正在用Java制作井字游戲程序,因為我正在學習Java,並且我認為一個簡單的項目將是一個不錯的起點。 到目前為止,這是我的代碼:

public class Start {
    public static void main(String[] args) {
    GameTicTacToe gameTicTacToe = new GameTicTacToe();
    gameTicTacToe.windowBirth();

    }
}

和,

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class GameTicTacToe implements ActionListener {
    private int gridSize = 3;
    private JButton[] gridButton = new JButton[(gridSize * gridSize)];
    private JPanel grid = new JPanel(new GridLayout(gridSize, gridSize, 0, 0));
    private JFrame windowTicTacToe = new JFrame("Tisk, Task, Toes");
    private int[] gridButtonOwner = new int[(gridSize * gridSize)];
    private int turn = 1;
    private int HolerHor, HolerVer, HolerDia1, HolerDia2;

    Thread winnerBlue = new Thread() {
        public void run() {
            for (int a = 0; a < 4; a++) {
                for (int i = 0; i < gridButton.length; i++) {
                    gridButton[i].setBackground(Color.BLUE);
                }
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                }
                for (int i = 0; i < gridButton.length; i++) {
                    gridButton[i].setBackground(Color.WHITE);
                }
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                }
            }
            for (int i = 0; i < gridButton.length; i++) {
                gridButton[i].setEnabled(true);
                gridButtonOwner[i] = 0;
            }
        }
    };
    Thread winnerRed = new Thread() {
        public void run() {
            for (int a = 0; a < 4; a++) {
                for (int i = 0; i < gridButton.length; i++) {
                    gridButton[i].setBackground(Color.RED);
                }
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                }
                for (int i = 0; i < gridButton.length; i++) {
                    gridButton[i].setBackground(Color.WHITE);
                }
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                }
            }
            for (int i = 0; i < gridButton.length; i++) {
                gridButton[i].setEnabled(true);
                gridButtonOwner[i] = 0;
            }
        }
    };
    public void windowBirth() {
        for (int i = 0; i < gridButton.length; i++) {
            gridButtonOwner[i] = 0;
            gridButton[i] = new JButton("");
            gridButton[i].addActionListener(this);
            gridButton[i].setBackground(Color.WHITE);
            grid.add(gridButton[i]);
        }
        windowTicTacToe.setDefaultCloseOperation(3);
        windowTicTacToe.setLocation(400, 200);
        windowTicTacToe.setPreferredSize(new Dimension(400, 400));
        windowTicTacToe.add(grid);
        windowTicTacToe.pack();
        windowTicTacToe.setVisible(true);
    }
    public void actionPerformed(ActionEvent gridButtonClicked) {
        for (int i = 0; i < gridButton.length; i++) {
            if (gridButtonClicked.getSource() == gridButton[i]) {
                if (turn == 1) {
                    turn = 2;
                    gridButtonOwner[i] = 1;
                    gridButton[i].setBackground(Color.blue);
                    gridButton[i].setEnabled(false);
                } else {
                    turn = 1;
                    gridButtonOwner[i] = 2;
                    gridButton[i].setBackground(Color.red);
                    gridButton[i].setEnabled(false);
                }
            }
        }
        checkWinner();
    }
    public void checkWinner() {
        for (int a = 1; a < 3; a++) {
            HolerDia1 = a;
            HolerDia2 = a;
            for (int b = 0; b < gridSize; b++) {
                HolerHor = a;
                HolerVer = a;
                for (int c2 = 0; c2 < gridSize; c2++) {
                    HolerHor = (HolerHor * gridButtonOwner[((b * gridSize) + c2)])/ a;
                    HolerVer = (HolerVer * gridButtonOwner[((c2 * gridSize) + b)])/ a;
                }
                if (HolerHor == a || HolerVer == a) {
                    winnerAnimation(a);
                }
            }
            for(int h = 0;h < gridSize; h++){
                HolerDia1 = (HolerDia1 * gridButtonOwner[h * (gridSize + 1)]) / a;
                HolerDia2 = (HolerDia2 * gridButtonOwner[(h * (gridSize - 1)) + (gridSize - 1)]) / a;
            }
            if (HolerDia1 == a || HolerDia2 == a) {
                winnerAnimation(a);
            }
        }
    }
    public void winnerAnimation(int b) {
        for (int i = 0; i < gridButton.length; i++) {
            gridButton[i].setEnabled(false);
        }
        if (b == 1){
            winnerBlue.start();
        }else{
            winnerRed.start();
        }
    }
}

這是我的問題,當玩家獲勝時,例如玩家1(藍色),它將播放動畫(將棋盤閃爍藍色)。 但是當玩家1再次獲勝時,程序崩潰。

我仔細研究了一下,發現您無法啟動線程兩次,因為您無法啟動。

我該如何暫停線程,然后在需要時重新啟動它?

您可以簡單地創建一個新線程並在需要時運行它。 但是無論如何,我都會使用Swing計時器來制作動畫,因為它更簡單,更安全,因為您不必擔心由於意外踩到Swing線程EDT而造成的間歇性崩潰。

例如

   public void myWinner(final Color flashColor) {
      int timerDelay = 300;
      new javax.swing.Timer(timerDelay , new ActionListener() {
         private static final int COUNTER_MAX = 5;
         int counter = 0;

         public void actionPerformed(ActionEvent e) {
            if (counter >= COUNTER_MAX) { // time to stop
               ((Timer)e.getSource()).stop();
               for (int i = 0; i < gridButton.length; i++) {
                  gridButton[i].setBackground(Color.white); // just to be sure
                  gridButton[i].setEnabled(true);
                  gridButtonOwner[i] = 0;
               }
            }
            Color bckgrndColor = (counter % 2 == 0) ? flashColor : Color.white;
            for (JButton button : gridButton) {
               button.setBackground(bckgrndColor);
            }
            counter++;
         }
      }).start();
   }

在您的情況下,在重播動畫線程時,您可能需要:

  • 將線程封裝為自己的Runnable對象,例如,創建匿名匿名Runnable而不是創建匿名Thread對象。
  • 然后只需重新創建線程並啟動它:

     public void winnerAnimation(int b) { ... if (b == 1) { animationThread = new Thread(winnerBlue); animationThread.start(); } else { animationThread = new Thread(winnerRed); animationThread.start(); } } 

    順便說一句,您可能需要考慮以下事實:在編寫ThreadRunnable時,Swing不是線程安全的。

使用信號量

  1. 在程序的開頭啟動線程。
  2. 每個run()方法應連續循環。
  3. 在循環的頂部,獲取()適當的信號量(紅色/藍色)。
  4. 當檢測到獲勝者時,釋放適當的信號量。

創建線程的另一個實例怎么了? 重用線程是令人討厭的,會導致真正奇怪的行為,通常不應該這樣做。

除了重復代碼(線程中只有1行不同,對嗎?),您可以簡單地將線程實現為內部類。 這樣,您不必使用匿名實例,並且可以重新創建和啟動任意多次。
您應該明確考慮將顏色添加為該線程的參數!

(我很確定這里有一個編譯器錯誤,但是您應該明白我的意思。)

// other stuff here...

public void winnerAnimation(int b) {
    for (int i = 0; i < gridButton.length; i++) {
        gridButton[i].setEnabled(false);
    }
    if (b == 1){
        new WinnerThread(Color.BLUE).start();
    }else{
        new WinnerThread(Color.RED).start();
    }
}

class WinnerThread extends Thread {
   private Color color;
   public WinnerThread(Color c)
   {
       color = c;
   }

   public void run() {
            for (int a = 0; a < 4; a++) {
                for (int i = 0; i < gridButton.length; i++) {
                    gridButton[i].setBackground(color);
                }
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                }
                for (int i = 0; i < gridButton.length; i++) {
                    gridButton[i].setBackground(Color.WHITE);
                }
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                }
            }
            for (int i = 0; i < gridButton.length; i++) {
                gridButton[i].setEnabled(true);
                gridButtonOwner[i] = 0;
            }
        }
    }
}

看看Java的wait()notify()方法。 是關於它們的教程。

可以使用以下功能暫停和恢復線程:

  • 暫停() =暫停
  • resume() =用於恢復

實現方式:

threadObject 暫停 ();

threadObject 簡歷 ();

但是我認為這些功能已被棄用。 雖然不確定。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM